Skip to content

safe-outputs: handler failures (success: false) computed in failureCount but never escalated to core.setFailed() #20035

@samuelkahessay

Description

@samuelkahessay

Context

Observed in production on 2026-03-07. A prd-decomposer workflow created 6 sub-issues from a PRD but the 7th failed handler validation (temporary_id: aw_ui — too short). The safe-outputs step reported success, the workflow dispatched downstream agents, and the missing feature was only discovered by manual audit.

Still reproducible on upstream gh-aw main at 548291897572e4f8007306613039c0e553bf1a32 and in v0.56.0.

Problem

When a safe-output handler returns {success: false}, the handler manager correctly counts the failure in failureCount but only emits core.warning(). It never calls core.setFailed(), so the step exits 0 and the workflow reports success.

This applies both to:

  • first-pass handler failures (for example, create_issue rejecting an invalid temporary_id)
  • deferred-message retry failures that come back as {success: false} on the retry pass

This is distinct from #19017 (permanently deferred items excluded from failureCount). Here, failureCount is already correct — the escalation path is what's missing.

Location

  • actions/setup/js/safe_output_handler_manager.cjs:316-330 — first-pass handler failure captured
  • actions/setup/js/safe_output_handler_manager.cjs:467-476 — deferred retry failure captured
  • actions/setup/js/safe_output_handler_manager.cjs:898failureCount computed
  • actions/setup/js/safe_output_handler_manager.cjs:927-929core.warning() only, no core.setFailed()
  • actions/setup/js/safe_output_handler_manager.cjs:994-995 — only core.setFailed() is in top-level catch

Reproduction

Minimal workflow config:

safe-outputs:
  create-issue: {}

Minimal agent output:

{"type":"create_issue","title":"Frontend","body":"Build the frontend","temporary_id":"aw_ui"}

Steps:

  1. Run any workflow that executes the consolidated safe-outputs step with the config above.
  2. Feed the handler manager the agent output above.
  3. create_issue validation rejects temporary_id: "aw_ui" and returns {success: false, error: "Invalid temporary_id format: 'aw_ui'..."}.
  4. safe_output_handler_manager.cjs records the failure and computes failureCount = 1.
  5. The step summary and logs show the failure, but the step still exits with code 0 because failureCount > 0 only triggers core.warning().
  6. The job and workflow continue as successful.

Expected behavior

When failureCount > 0, the safe-outputs step should call core.setFailed() so the step, job, and workflow all report failure.

Proposed fix

Add core.setFailed() when failureCount > 0:

if (failureCount > 0) {
  core.warning(`${failureCount} message(s) failed to process`);
  const failedItems = processingResult.results
    .filter(r => !r.success && !r.deferred && !r.skipped && !r.cancelled)
    .map(r => `  - ${r.type}: ${r.error}`)
    .join('\n');
  core.setFailed(`${failureCount} safe output(s) failed:\n${failedItems}`);
}

Environment

  • Observed in production: v0.52.1-generated workflows
  • Still present on: upstream main at 548291897572e4f8007306613039c0e553bf1a32; also verified in v0.56.0
  • Repo: samuelkahessay/to-do-app-with-weather-and-notification-preferences

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions