Skip to content

[aw-failures] Fix malformed JSON emission for approve_workflow_run.allowed_pull_requests in safe-outputs config builder #53806

Description

@github-actions

Problem

safe_outputs job crashes on startup for every PR Sous Chef run — 18 of 24 failed runs in the last 6h — with:

##[error]ERR_VALIDATION: Handler manager failed: ERR_PARSE: Failed to parse GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG: Expected ',' or '}' after property value in JSON at position 200 (line 1 column 201)

No safe output (comments, PR pushes, issue creation) is ever processed for the run once this hits — the agent job's work is silently dropped.

Affected workflows and runs

Probable root cause

.github/workflows/pr-sous-chef.lock.yml:2566 (and the equivalent GH_AW_SAFE_OUTPUTS_CONFIG at line 837) embed the PR allow-list as a quoted JSON string:

\"allowed_pull_requests\":\"${{ needs.approval_allowlist.outputs.eligible_pull_request_numbers }}\"

needs.approval_allowlist.outputs.eligible_pull_request_numbers (lock.yml:1515) is produced by jq -c '[.prs[]?.number | tostring]', so at runtime it already renders as a JSON array literal, e.g. ["53698","53725","53720"]. GitHub Actions performs a literal text substitution with no re-escaping for the surrounding JSON-string context, so the array's own quotes collide with the wrapping quotes and the JSON breaks. Reproduced locally: feeding the captured GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG text to a JSON parser fails at the exact same field with "expected ',' or '}'".

This is generated by AddTemplatableStringSlice in pkg/workflow/compiler_safe_outputs_builder.go:63-75, invoked for this field at pkg/workflow/safe_outputs_handler_registry.go:300. When a field's value is a single-element slice matching ${{ ... }} (isExpression, pkg/workflow/expression_patterns.go:95), the builder stores the raw expression string as a scalar (b.config[key] = value[0]), which json.Marshal then wraps in quotes when the final config map is serialized. That's only safe when the expression's runtime output is a plain scalar with no embedded quote/bracket characters — it silently corrupts the JSON whenever the expression's output is itself JSON (arrays/objects), which is exactly what eligible_pull_request_numbers produces.

The consumer, parseAllowedPullRequests in actions/setup/js/approve_workflow_run.cjs:36-49, already handles either a real JSON array or a bracket-string via JSON.parse — it expects unquoted array splicing, not a quoted-string wrapper. So this is purely an emission-side bug, not a consumer defect.

Proposed remediation

  1. In pkg/workflow/compiler_safe_outputs_builder.go, change how AddTemplatableStringSlice renders the single-expression case for allowed_pull_requests (and audit other callers at lines 97-98, 442, 556-560, 568-570, 629, 637, 736-737 for the same risk): emit the expression unquoted ("allowed_pull_requests":${{ expr }}) when the field is documented/known to accept a JSON array at runtime, instead of wrapping it as a JSON string.
  2. Add a regression test asserting that GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG generated for a workflow using approve_workflow_run with a dynamic allowed_pull_requests expression is valid JSON after simulating the ${{ }} substitution with a multi-element array value (e.g. ["123","456"]) — this is exactly the case the current unit tests miss (pkg/workflow/approve_workflow_run_test.go, approve_workflow_run_integration_test.go presumably only exercise static/single-value cases).
  3. Recompile and republish pr-sous-chef.lock.yml (and any other lock file using the same pattern — grep AddTemplatableStringSlice call sites against fields that receive jq -c '[...]'-style outputs) to confirm the generated JSON parses cleanly.

Success criteria / verification

  • GH_AW_SAFE_OUTPUTS_HANDLER_CONFIG/GH_AW_SAFE_OUTPUTS_CONFIG in the recompiled pr-sous-chef.lock.yml parses as valid JSON when eligible_pull_request_numbers evaluates to a multi-element array (not just [] or a single element).
  • Next PR Sous Chef run's safe_outputs job completes without the ERR_PARSE error.
  • The [aw] Failed jobs: PR Sous Chef notifier issue stops recurring on every trigger (existing 30+ open duplicates can then be left to self-expire).
    Related to [aw-failures] [aw] Failure Investigator Report — 2026-08-18 19:00 UTC (6h) #53804

Generated by 🔍 [aw] Failure Investigator (6h) · agent · 165.4 AIC · ⌖ 12.6 AIC · ⊞ 5.9K ·

  • expires on Aug 25, 2026, 11:15 AM UTC-08:00

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions