Skip to content
Latchkey

Azure Pipelines Macro "$( )" Not Expanding in a Step

A $(var) macro is substituted at the start of a step. If the variable is not set yet, is a secret (deliberately not auto-injected), or is an output variable from a step in the same job, the macro prints literally or comes back empty.

What this error means

A script echoes $(MY_VAR) verbatim, or the value is blank. The variable exists elsewhere in the pipeline, but at this step’s start it was unset, secret, or produced too late.

Azure DevOps
+ echo $(API_KEY)
$(API_KEY)            # printed literally - secret not mapped to env

Common causes

Secret variable not mapped to env

Secret variables (from a variable group or marked secret) are NOT auto-expanded into scripts. You must map them explicitly via env: so the value is available without being logged.

Output variable consumed too early

A variable set by an earlier step with isOutput=true is referenced as $(step.var) and must be consumed in a later step - not the same one - within the job.

How to fix it

Map secrets explicitly into env

Pass the secret through env: and read it from the environment in the script.

azure-pipelines.yml
steps:
  - bash: |
      echo "len is ${#API_KEY}"   # use env, never echo the secret
    env:
      API_KEY: $(apiKeySecret)

Reference output variables in a later step

Read a step output via the stepName.var macro in a subsequent step.

azure-pipelines.yml
steps:
  - bash: echo "##vso[task.setvariable variable=tag;isOutput=true]v1"
    name: produce
  - bash: echo "$(produce.tag)"   # consumed in a later step

How to prevent it

  • Always map secret variables via env:; never rely on macro auto-expansion.
  • Consume output variables in a different step than the one that sets them.
  • Never echo secrets - read their length or use them, do not print them.

Frequently asked questions

What causes ""$( )" prints literally"?
Secret variables (from a variable group or marked secret) are NOT auto-expanded into scripts. You must map them explicitly via env: so the value is available without being logged.
How do I fix "$( )" prints literally?
Pass the secret through env: and read it from the environment in the script.

Related guides

References

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