Azure Pipelines: "A template expression is not allowed in this context"
A template expression, ${{ ... }}, is worked out once, when Azure Pipelines compiles the YAML, before anything runs. It is expanded only in some parts of the file. In any other part, the pipeline does not start and the editor or the run reports this error with the file, line and column.
When the pipeline is a pull request's build validation, the pull request waits on it: Azure DevOps Pull Requests, a plugin for JetBrains IDEs, lists the pull request's branch policies with their state in IntelliJ IDEA, Rider or PyCharm, and with Pro runs a failed build policy again once the YAML is fixed. Get it on JetBrains Marketplace
Where ${{ }} is expanded
- Microsoft's page on template expressions says they are expanded for stages, jobs, steps and containers, and gives
triggeras a place where they are not. - The Sprint 212 release notes (2022) added template expressions to repository and container resources. Microsoft's YAML reference for a repository resource lets
reftake parameters and predefined system variables, not variables defined in the YAML or in the pipeline settings;nametakes no variables. - Only values known at compile time can be used, such as parameters. Variables set in the pipeline settings, in variable groups or by a script are not known at that point.
Triggers
- Microsoft's page on Azure Repos triggers says variables cannot be used in triggers, because variables are evaluated after the trigger has fired. Expressions are not expanded there either. Write the branch and path names out in
triggerandpr. - Triggers can only be in the main YAML file, not in a template. If the branches differ by pipeline, give each pipeline its own small main file that includes the shared templates.
- For pull requests in Azure Repos, a branch policy with build validation decides which pull requests run the pipeline, and it is set per branch outside the YAML.
Parameter defaults
- A parameter's
defaultis a plain value. An expression there is not worked out, so a default that depends on a variable or another parameter has to be written where expressions are expanded. - The pattern on Microsoft's page: an empty default, and
coalescewhere the value is used.
parameters:
- name: customVersion
type: string
default: ''
- name: defaultVersion
type: string
default: '1.0.0'
steps:
- script: echo Version is ${{ coalesce(parameters.customVersion, parameters.defaultVersion) }}
Pool and container names
- A pool chosen by a parameter works at the stage or job level, where expressions are expanded:
pool: ${{ parameters.poolName }}inside the job. Microsoft's page on runtime parameters has an example that lets the person running the pipeline choose the pool image. - For a value known only at run time, such as a variable from a variable group, use macro syntax
$(name)in a task input, or a runtime expression$[ ]in a condition or a variable. Neither works in triggers, resources or the shape of the pipeline.
Azure DevOps pull requests in IntelliJ IDEA, Rider and PyCharm
Azure DevOps Pull Requests, a plugin by Lesstep for JetBrains IDEs 2024.1 or later and Android Studio, reads the organization, project and repository from your git remote and lists the pull requests that wait for your review in an IDE tool window, on Azure DevOps Services and on Azure DevOps Server. It shows the branch policies of a pull request with their state, so a required build that has not passed is next to its pull request, and with Pro you run a failed or expired build policy again from there. The review inbox is free; voting, commenting, completing and creating are Pro, with a 30-day trial.
Get it on JetBrains Marketplace
Azure DevOps and Azure Pipelines are trademarks of Microsoft Corporation; IntelliJ IDEA, Rider and PyCharm are trademarks of JetBrains s.r.o. This page is not affiliated with or endorsed by Microsoft or JetBrains.
More: Build validation · This pipeline needs permission to access a resource · 日本語