Passing parameters to a child pipeline or workflow
This page is the reference for one question: when pipeline or workflow A starts B, what value does a parameter of B end up with?
The answer is the same for every action and transform that starts a child:
-
Pipeline action
-
Workflow action
-
Pipeline Executor transform
-
Workflow Executor transform
-
Simple Mapping and Multi Mapping transforms
-
Metadata Injection transform
-
Repeat action
Throughout this page, caller is the pipeline or workflow that starts another one, and child is the one being started.
The two controls
Each of those actions and transforms gives you two things, and they answer different questions.
The Parameters tab is a grid. Each row names a parameter and says where its value comes from: a fixed value, a variable expression, or a field from the incoming row. A row that supplies a value always wins.
The checkbox Pass parent values to matching parameters answers a different question: what to do about the parameters you did not list. With the option on, the caller’s own value of that name is passed down. With it off, the child keeps its own default.
| Neither control has anything to do with variable inheritance. A child always inherits the caller’s variables. The option only decides whether a parameter declared by the child is filled in from the caller or keeps its own default. This is a common misreading, because the option used to be labelled "Inherit all variables from pipeline". |
The rules
For each parameter the child declares, in this order:
-
A row on the caller’s Parameters tab that supplies a value. This wins over everything, including the checkbox. It is how you override a child’s default for one execution.
-
Otherwise, if Pass parent values to matching parameters is on: the caller’s value of a parameter or variable with that same name.
-
Otherwise: the child’s own default, as declared in the child’s pipeline or workflow properties.
-
If the child declares no default either, the parameter is an empty string.
A row that names a parameter the child does not declare is not ignored: that parameter is declared on the child and set, so the child can use ${NAME} as if it had declared it itself.
What counts as "supplies a value"
Rule 1 only applies to a row that actually configures something. Three cases look similar and behave differently on purpose:
| The row | What happens |
|---|---|
A value or variable expression is filled in | That value is used. Rule 1. |
A field is mapped, and the field is empty on this row | You did configure a source, it just produced nothing this time. The child falls back to its own default. It does not reuse the value from a previous row. |
No value and no field - only the name | Nothing is configured, so the row is treated as if it were not there. The option and the child’s default decide, as in rules 2 and 3. |
The last case matters more than it looks. Pressing Get Parameters fills the grid with the names the child declares and leaves the values empty. Those rows do not pass anything by themselves; whether the caller’s values reach the child is still decided by the checkbox.
The full picture
A child that declares MY_PARAM with default child-default, a caller whose scope holds MY_PARAM=parent-value:
| Caller’s Parameters tab | Option off | Option on |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The two bottom rows are the reason a parameter is worth declaring: a child that declares a parameter is shielded from an unrelated value of the same name that happens to exist in the caller, unless you deliberately allow it.
Things that surprise people
You cannot blank out a parameter by leaving the value empty
An empty parameter value means "nothing was passed", so the child’s default applies. There is no way to force a parameter that has a non-empty default to become an empty string from the caller.
If the child must be able to run with an empty value, declare it in the child with an empty default. It is then empty unless something passes a value.
A variable and a parameter of the same name are not the same thing
The child inherits MY_PARAM=parent-value as a variable either way. But if the child also declares MY_PARAM as a parameter, activating that parameter sets the variable in the child’s scope, so the parameter is what you read. That is the point of declaring it, and it is why two independently written pipelines that happen to use the same name do not contaminate each other.
If a value really is environment-wide, do not declare it as a parameter at all. Just read ${NAME}: it is inherited, and nothing overwrites it.
A child that is already running does not see new values
Parameters are handed over when the child starts. Set a variable, then start the child. See Fields, parameters, and variables.
Per-executor notes
| Executor | Notes |
|---|---|
Pipeline / Workflow action | The Parameters tab also has a Copy results to parameters option, which pre-fills the values from the incoming result rows before the rules above are applied. |
Pipeline / Workflow Executor | Parameters are set once per executor iteration, from the first row of the group. A child started for the next row starts over from these rules; nothing carries over. |
Mapping / Multi Mapping | Same rules. The grid has no field column, so only the "value filled in" and "nothing configured" cases occur. |
Metadata Injection | Same rules, applied to the template pipeline. Files saved before the Parameters tab existed behave as if the option is on, which is what they always did. |
Repeat | Same rules per repetition. Keep variable values between executions wins over the Parameters tab, so a value can accumulate across repetitions. |
See also
-
Variables - syntax, hierarchy, resolvers, built-in names
-
Fields, parameters, and variables - how the three concepts differ