secrets: inherit Not Working in Reusable Workflows - Fix
A called (reusable) workflow reads a secret as empty because the caller did not forward it. Reusable workflows do not see the caller's secrets automatically - each must be passed in the secrets: block or via secrets: inherit.
What this error means
A reusable workflow's step gets an empty secret value, so an API call or deploy fails, even though the secret exists in the calling repo. The caller never forwarded it to the called workflow.
# caller - secrets not forwarded
jobs:
build:
uses: ./.github/workflows/deploy.yml
# missing: secrets: inherit (or an explicit secrets: map)
# in deploy.yml, secrets.DEPLOY_TOKEN is emptyCommon causes
Caller did not pass secrets
A reusable workflow only receives secrets the caller explicitly forwards. Omitting both the secrets: map and secrets: inherit leaves them undefined in the called workflow.
Called workflow did not declare the secret
When forwarding explicitly (not inherit), the called workflow must declare each secret under on.workflow_call.secrets, or it will not be available.
How to fix it
Forward secrets explicitly or inherit
Pass the needed secrets by name, or use secrets: inherit to forward all of the caller's secrets.
# caller
jobs:
deploy:
uses: ./.github/workflows/deploy.yml
secrets:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
# or, to pass everything:
# secrets: inheritDeclare secrets in the called workflow
- Add each forwarded secret under on.workflow_call.secrets in the called workflow.
- Use secrets: inherit only when the caller is trusted to expose all its secrets to the called workflow.
- For nested reusable workflows, forward at every level - inheritance is not transitive unless each level inherits.
How to prevent it
- Forward reusable-workflow secrets explicitly, or use secrets: inherit deliberately.
- Declare on.workflow_call.secrets in the called workflow.
- Forward at each nesting level; inheritance is not automatic deep down.