Skip to content
Latchkey

GitHub Actions "Unexpected value 'secrets'" in a reusable workflow in CI

The secrets: key is only valid in two places: a calling job that uses a reusable workflow, and the on.workflow_call.secrets block of a reusable workflow. Anywhere else GitHub reports "Unexpected value 'secrets'".

What this error means

Parsing fails with "Unexpected value 'secrets'". The secrets: block sits on an ordinary job with steps, at the top level, or under a wrong key.

GitHub Actions
Invalid workflow file: .github/workflows/ci.yml#L7
Unexpected value 'secrets'
A job may only use "secrets" when it calls a reusable workflow with "uses".

Common causes

secrets on a normal (steps) job

A job that runs steps cannot have a job-level secrets: block. Only a calling job that uses a reusable workflow may pass secrets.

secrets declared under the wrong key in the callee

In a reusable workflow, secrets must be declared under on.workflow_call.secrets, not directly under on: or under a job.

How to fix it

Only use secrets: on a calling job

  1. Move the secrets: block to the job that has uses: for the reusable workflow.
  2. Remove secrets: from any job that runs steps.
  3. Read secrets in a steps job via ${{ secrets.X }} directly.
.github/workflows/ci.yml
jobs:
  deploy:
    uses: ./.github/workflows/deploy.yml
    secrets:
      DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}

Declare callee secrets under workflow_call

In the reusable workflow, put secret declarations under on.workflow_call.secrets.

.github/workflows/deploy.yml
on:
  workflow_call:
    secrets:
      DEPLOY_TOKEN:
        required: true

How to prevent it

  • Use job-level secrets: only on calling jobs.
  • Declare reusable-workflow secrets under on.workflow_call.secrets.
  • Read secrets directly with ${{ secrets.X }} in normal jobs.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →