Skip to content
Latchkey

GitLab CI Variable Expansion Errors - Empty or Wrong Values in Rules

A $VARIABLE resolved to empty or to the wrong value. GitLab expands variables in defined phases, and a value not yet set at rule-evaluation time, or an over-escaped $$, breaks the logic.

What this error means

A rule never matches because the variable it tests is empty, a script prints a literal $VAR instead of its value, or a nested variable reference does not resolve. The config is valid - the value is just not what you expect.

Job rules / script
# Rule never matches because the variable is set in the same job, not at rule time:
deploy:
  variables:
    TARGET: production
  rules:
    - if: '$TARGET == "production"'   # $TARGET evaluated before job vars apply

Common causes

Variable not available at rule-evaluation time

Rules are evaluated when the pipeline is created. A job-level variables: value, or one set later in a script, is not yet defined when its own rules are checked.

Nested expansion not enabled or mis-keyed

Referencing one variable inside another ($$NAME or ${${NAME}}) only works with the supported nested-expansion syntax. A wrong form yields a literal string.

Over-escaping with $$

In .gitlab-ci.yml, $$ is a literal dollar sign. Using $$VAR when you meant $VAR makes GitLab emit a literal $VAR instead of expanding it.

How to fix it

Define rule variables at the right scope

Use predefined or top-level variables in rules, or rules:variables so the value exists when the rule runs.

.gitlab-ci.yml
deploy:
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
      variables:
        TARGET: production
  script:
    - echo "deploying to $TARGET"

Escape literals deliberately

Use $$ only when you want a literal dollar sign reaching the shell; use a single $ to expand a CI variable.

.gitlab-ci.yml
script:
  - echo "CI value: $CI_COMMIT_SHA"      # expanded by GitLab
  - echo "shell var: $$HOME"             # literal $HOME, expanded by the shell

How to prevent it

  • Test rule variables against predefined CI variables that exist at creation time.
  • Use rules:variables to set values that conditionally apply.
  • Reserve $$ for intentional literal dollars passed to the shell.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →