Ci::CreateDownstreamPipelineWorker fails when pipeline variable has null value and forward:pipeline_variables is true
Summary
When a pipeline is triggered via the API with a variable whose value is null, and the bridge job is configured with forward: pipeline_variables: true, GitLab's variable expansion machinery crashes with an unhandled NoMethodError inside a Sidekiq worker (Ci::CreateDownstreamPipelineWorker). The downstream pipeline is never created and a data integrity failure error is displayed in the UI.
Steps to Reproduce
1. Parent pipeline .gitlab-ci.yml must have forward: pipeline_variables: true:
trigger-downstream:
trigger:
project: my-group/second-project
forward:
pipeline_variables: true2. Downstream project .gitlab-ci.yml file:
trigger-downstream:
script:
- echo "downstream"3. Trigger the parent pipeline via the API with a null-valued variable:
curl --request POST \
--header "PRIVATE-TOKEN: $TOKEN" \
--header "Content-Type: application/json" \
--data '{
"ref": "main",
"variables": [{ "key": "MY_VAR", "value": null }]
}' \
"https://gitlab.com/api/v4/projects/<PROJECT_ID>/pipelines"4. Observe — the trigger-downstream bridge job fails, the downstream pipeline is never created, and the Sidekiq worker logs a NoMethodError.
Logs:
exception.backtrace": [
"lib/expand_variables.rb:39:in `replace_with'",
"lib/expand_variables.rb:10:in `expand'",
"lib/gitlab/ci/variables/downstream/expandable_variable_generator.rb:20:in `expanded_var_for'",
"lib/gitlab/ci/variables/downstream/expandable_variable_generator.rb:9:in `for'",
"lib/gitlab/ci/variables/downstream/generator.rb:71:in `block in build_downstream_variables_from'",
"lib/gitlab/ci/variables/collection.rb:53:in `block in each'",
"lib/gitlab/ci/variables/collection.rb:53:in `each'",
"lib/gitlab/ci/variables/collection.rb:53:in `each'",
"lib/gitlab/ci/variables/downstream/generator.rb:67:in `flat_map'",
"lib/gitlab/ci/variables/downstream/generator.rb:67:in `build_downstream_variables_from'",
"lib/gitlab/ci/variables/downstream/generator.rb:49:in `downstream_pipeline_variables'",
"lib/gitlab/ci/variables/downstream/generator.rb:35:in `calculate_downstream_variables'",
"lib/gitlab/ci/variables/downstream/generator.rb:20:in `calculate'",
"app/models/ci/bridge.rb:267:in `downstream_variables'",
"app/models/ci/bridge.rb:397:in `child_params'",
"app/models/ci/bridge.rb:119:in `downstream_pipeline_params'",
"app/services/ci/create_downstream_pipeline_service.rb:29:in `execute'",
"app/workers/ci/create_downstream_pipeline_worker.rb:20:in `block in perform'",
"activesupport (7.2.3) lib/active_support/core_ext/object/try.rb:12:in `try'",
"app/workers/ci/create_downstream_pipeline_worker.rb:17:in `perform'",Current Behavior
meta.root_caller_id: PUT /api/:version/jobs/:id
meta.caller_id: PipelineProcessWorker,
class: Ci::CreateDownstreamPipelineWorker
exception.class: NoMethodError
exception.message: undefined method `gsub' for nilThe Sidekiq worker (Ci::CreateDownstreamPipelineWorker) crashes.
Expected Behavior
The system should either:
- Detect the
nullvalue early and fail gracefully with a clear error message visible on the bridge job in the UI, or - Silently skip/drop
nil-valued variables before they reach the variable expander
Workaround
Remove forward: pipeline_variables: true from the bridge job configuration, or ensure that all variables passed via the API trigger have non-null string values.
Environment
- Reproducible in GitLab.com and Self-Managed instances
