This happens because template expansion is done before variable expansion (docs). Variable references like $(Foo)
are not yet processed when the template parameter type is validated.
The first step in pipeline processing is only about replacing all template: xxx
references in the YAML tree with the target YAML elements, and handling template parameters and any encountered template (compile-time) expressions, which look like ${{ ... }}
.
The error message which goes like
“The 'someVar' parameter value '$(SOME_VAR)' is not a valid Boolean.
”
does not mean that the content of the variable SOME_VAR
is wrong (not true
or false
).
It means that the literal text $(SOME_VAR)
, i.e. including the dollar sign, the parentheses and the variable name, is not a valid boolean value. Because that's all the parser sees at the time it is doing this early template expansion.
If the type of the template parameter was changed to a string
, it would naturally accept even the value of $(SOME_VAR)
. But an expression like ${{ parameters.someVar }}
encountered later inside the template would not be replaced with a True
or False
, as one might expect.
It would rather be replaced again just with the literal text $(SOME_VAR)
, as it is. And only later, when actually running the relevant step or doing other evaluation, it might get replaced with the real value the variable has at the moment (that is, if these variable expansions are allowed in the given context at all).
(On the other hand, it is superfluous to reference boolean
template parameters in constructs formatted like e.g. condition: eq(${{ parameters.someVar }}, 'true')
. The inner expression will already only ever expand to the real true
or false
value, so just condition: ${{ parameters.someVar }}
is enough.)
The docs specify that only "parameters and statically defined variables" can be accessed from the compile-time template expressions in format ${{ ... }}
. This means that even if there is a syntax which allows referencing variables like variables.Foo
or variables['Foo']
, it does not work for all of them at this time.
The list of predefined variables has a dedicated column "Available in templates?", which shows whether it is possible to use each of them during the early template expressions evaluation or not.
What "statically defined" means with user-defined variables, the variable must be set in the variables
section of the YAML file. Providing it only in the pipeline definition or only when starting the build in the ADO UI would not work (it would expand to an empty string). But variables set statically in the YAML file cannot be set (overridden) from the UI at all, which is quite limiting...
My suggestion is to use parameters
instead of variables
at least for values that are supposed to be changed by users sometimes.
They are much better than variables for this purpose, allowing one to prepare a nice UI with properly labeled text boxes, checkboxes, radio buttons etc., instead of the poor string-only variables experience:

And well, most importantly, they work when passed as parameters further to templates.
But yes, they are not a replacement for things like variable groups. Changing the inner template might be needed then, to reference relevant variables directly, or take string
parameters instead of typed boolean
etc. after all.