Skip to content
Latchkey

GitLab CI Protected Variable Empty on Unprotected Branch

A CI/CD variable read as empty because it is marked "protected". Protected variables are only injected on pipelines for protected branches and tags - not on feature branches or merge-request pipelines.

What this error means

A deploy or auth step fails because a secret is blank on a feature branch but works on main. The variable is defined, yet the job sees an empty value depending on the ref.

Job log
$ echo "deploying with token length: ${#DEPLOY_TOKEN}"
deploying with token length: 0
$ ./deploy.sh
Error: missing DEPLOY_TOKEN

Common causes

Variable is protected, branch is not

A "Protected" CI/CD variable is exposed only to pipelines running on protected branches/tags. On an unprotected feature branch it is simply not present.

Masking constraints silently drop it

A "Masked" variable whose value does not meet GitLab’s masking requirements may be disabled, leaving the job without it.

How to fix it

Run the job on a protected ref or unprotect the variable

  1. If the secret is only for deploys, gate the job to protected branches/tags with rules.
  2. If it must run on feature branches, uncheck "Protected" on the variable (accepting the broader exposure).
  3. Protect the branch/tag pattern that legitimately needs the secret.

Verify presence before using it

Fail fast with a clear message instead of a confusing downstream error.

.gitlab-ci.yml
deploy:
  rules:
    - if: '$CI_COMMIT_BRANCH == "main"'
  script:
    - test -n "$DEPLOY_TOKEN" || { echo "DEPLOY_TOKEN missing (protected?)"; exit 1; }
    - ./deploy.sh

How to prevent it

  • Keep deploy secrets protected and gate deploy jobs to protected refs.
  • Document which variables are protected so contributors expect the behavior.
  • Ensure masked values satisfy GitLab’s masking rules so they are not disabled.

Frequently asked questions

What causes "Protected variable empty"?
A "Protected" CI/CD variable is exposed only to pipelines running on protected branches/tags. On an unprotected feature branch it is simply not present.
How do I fix Protected variable empty?
Run the job on a protected ref or unprotect the variable

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card