Skip to content
Latchkey

GitHub Actions needs.<job>.outputs undefined when upstream skipped

A downstream job reads needs.<job>.outputs.* only when the upstream job ran and set them. A skipped upstream, or one that never wrote GITHUB_OUTPUT, yields empty values.

What this error means

A consumer job sees an empty needs output and behaves as if the value was never set, often after the producer was skipped or did not write the output.

github-actions
# needs.setup.outputs.tag is '' because 'setup' was skipped
echo "tag=${{ needs.setup.outputs.tag }}"

Common causes

Upstream job skipped

A skipped producer never executes its steps, so no outputs are set.

Output not declared at job level

Job outputs must be mapped from a step output via jobs.<id>.outputs.

How to fix it

Declare outputs and guard consumption

  1. Map step outputs to job outputs under jobs.<id>.outputs.
  2. Ensure the producer actually runs (check its if).
  3. Default in the consumer: \${{ needs.setup.outputs.tag || 'latest' }}.
.github/workflows/ci.yml
setup:
  runs-on: ubuntu-latest
  outputs:
    tag: ${{ steps.t.outputs.tag }}
  steps:
    - id: t
      run: echo "tag=v1.2.3" >> "${GITHUB_OUTPUT}"

How to prevent it

  • Always map step outputs to job outputs explicitly.
  • Default consumer expressions so a skipped producer does not break logic.

Frequently asked questions

What causes "needs output undefined"?
A skipped producer never executes its steps, so no outputs are set.
How do I fix needs output undefined?
Declare outputs and guard consumption

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card