GitHub Actions Reusable Workflow Outputs Empty in the Caller
A caller reads a reusable workflow’s output and gets an empty string. workflow_call outputs must be declared and mapped from a job output inside the reusable workflow, then consumed via needs.<job>.outputs in the caller.
What this error means
After calling a reusable workflow with uses:, the caller reads needs.<job>.outputs.<name> and gets nothing, even though a step inside the reusable workflow produced the value.
# caller
jobs:
build:
uses: ./.github/workflows/build.yml
use:
needs: build
steps:
- run: echo "${{ needs.build.outputs.version }}" # emptyCommon causes
workflow_call outputs not declared
A reusable workflow only surfaces outputs listed under on.workflow_call.outputs. A step or job output alone does not reach the caller.
Output not mapped from a job
Each workflow_call output must reference a job output via jobs.<id>.outputs. Skipping that mapping leaves the caller-visible output empty.
How to fix it
Declare and map the workflow_call output
Expose the output at the workflow_call level, sourced from a job output that itself maps a step output.
# build.yml (reusable)
on:
workflow_call:
outputs:
version:
value: ${{ jobs.compile.outputs.version }}
jobs:
compile:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.v.outputs.version }}
steps:
- id: v
run: echo "version=1.2.3" >> "$GITHUB_OUTPUT"Read it via needs in the caller
- Add needs: on the consuming job so it waits for the reusable call.
- Reference needs.<call-job>.outputs.<name> in the caller.
- Confirm each name lines up: step output → job output → workflow_call output.
How to prevent it
- Declare workflow_call outputs and chain them from job and step outputs.
- Keep output names consistent across the three levels.
- Echo the value inside the reusable workflow to confirm it is non-empty.