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.
+ echo $(API_KEY)
$(API_KEY) # printed literally - secret not mapped to envCommon 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.
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.
steps:
- bash: echo "##vso[task.setvariable variable=tag;isOutput=true]v1"
name: produce
- bash: echo "$(produce.tag)" # consumed in a later stepHow 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.