GitLab CI Error Guide: 'job needs job, but it was not added to the pipeline' Fix
Fix GitLab's 'deploy job needs build job, but it was not added to the pipeline': align rules, reorder stages, use needs:optional, and check filtered jobs.
- #gitlab-cicd
- #troubleshooting
- #errors
- #pipelines
Exact Error Message
GitLab rejects the pipeline at validation time when a job’s needs: points at a job that will not be part of the pipeline:
'deploy' job needs 'build' job, but it was not added to the pipeline
jobs:deploy needs 'build' is not defined in prior stages
'deploy' job needs 'build' job, but 'build' is not in any previous stage
The message names the consumer (deploy) and the missing producer (build). It appears on push, in the Pipeline Editor’s Validate tab, from glab ci lint, and at /-/ci/lint.
What the Error Means
needs: builds an explicit dependency graph so jobs can start as soon as their dependencies finish, rather than waiting for a whole stage. For that graph to be valid, every job named in a needs: array must actually exist in the pipeline that is being created. GitLab evaluates rules, only/except, and workflow first to decide which jobs make the cut, then validates the needs graph against that final set.
So the error does not mean build is undefined in the file. It means that, for this pipeline, build was filtered out, named wrong, in the wrong stage, or simply not present — and deploy is still demanding it. The fix is to make the producer present (or make the dependency optional), not to rewrite deploy’s script.
Common Causes
- The producer is filtered out by
rules/only/except.buildruns only onmain, butdeploy(and itsneeds: [build]) is evaluated on a branch wherebuildis excluded. - The producer is in a later or the same stage.
needs:may reference a job only if that job runs in an earlier stage (or you must explicitly allow same-stage with the dependency present). - Typo in the job name.
needs: ["biuld"]references a job that does not exist. - Cross parent-child pipeline boundary. A child pipeline job cannot
needs:a job that lives only in the parent pipeline (and vice versa). - The producer lives in an
included set that was not merged. A broken or conditional include meansbuildnever made it into the merged config. - A required need that should be optional. The dependency is genuinely absent in some pipelines by design, but
needs:treats it as mandatory.
How to Reproduce the Error
Define build to run only on main, but let deploy need it everywhere:
stages: [build, deploy]
build:
stage: build
script: ["make build"]
rules:
- if: '$CI_COMMIT_BRANCH == "main"'
deploy:
stage: deploy
script: ["make deploy"]
needs: ["build"]
rules:
- if: '$CI_COMMIT_BRANCH' # runs on every branch
On a feature branch, build is filtered out but deploy still needs it:
'deploy' job needs 'build' job, but it was not added to the pipeline
A same-stage need fails the same way:
test:
stage: test
script: ["make test"]
needs: ["lint"] # lint is also stage: test -> not a prior stage
Diagnostic Commands
Lint with includes expanded so the full job set is visible:
glab ci lint --include
✗ Invalid configuration
'deploy' job needs 'build' job, but it was not added to the pipeline
Inspect how rules evaluate for the ref you are pushing. Simulate by checking the predefined variables the rule keys on:
# What branch/source will the pipeline see?
echo "$CI_COMMIT_BRANCH / $CI_PIPELINE_SOURCE"
List which jobs actually exist in the merged config and their stages:
glab ci lint --include | grep -E 'job|stage'
In the UI, open Project > Build > Pipeline Editor > Full configuration to see the merged YAML, then the Validate tab. The merged view confirms whether build is even present and which stage it sits in. The pipeline graph view (on a created pipeline) shows the resolved needs edges.
Step-by-Step Resolution
Fix a typo’d or wrong target — make needs: name a job that exists exactly:
deploy:
needs: ["build"] # must match the producing job's name verbatim
Align rules between producer and consumer — if deploy can run on a branch, build must too, or the need must be optional:
build:
stage: build
script: ["make build"]
rules:
- if: '$CI_COMMIT_BRANCH' # now runs wherever deploy can run
deploy:
stage: deploy
script: ["make deploy"]
needs: ["build"]
rules:
- if: '$CI_COMMIT_BRANCH'
Make the dependency optional — when the producer is legitimately absent in some pipelines, mark the need optional so its absence does not block the consumer:
deploy:
needs:
- job: build
optional: true
With optional: true, deploy runs even when build was filtered out, and consumes its artifacts only if build is present.
Reorder stages — a needs: target must run in an earlier stage. Move the producer up:
stages: [lint, test, deploy] # lint now precedes test
lint:
stage: lint
script: ["make lint"]
test:
stage: test
script: ["make test"]
needs: ["lint"] # lint is now a prior stage
Cross-pipeline needs — a child pipeline cannot need a parent job. Pass results across the boundary with artifacts or a trigger relationship instead of needs:.
Re-run glab ci lint --include until it reports Configuration is valid, then create a pipeline and confirm the needs edges in the graph.
Prevention and Best Practices
- Keep
rules:consistent between a producer and every job thatneeds:it; if a consumer can run somewhere, its producers must run there too, or be markedoptional: true. - Prefer
needs:withoptional: truefor dependencies that are conditionally present, so a filtered-out producer degrades gracefully instead of failing validation. - Order
stages:so everyneeds:target sits in an earlier stage; same-stage or later-stage needs are a frequent trap. - Lint with
--includein CI so the full merged job set — not just the file you edited — is validated. - Use the Pipeline Editor’s merged-YAML and pipeline-graph views to confirm both that the producer exists and that the
needsedge resolves the way you expect. - The free incident assistant can map a
needsvalidation error to a likely cause; more patterns live in the GitLab CI/CD guides.
Related Errors
- No pipeline created / workflow rules dropped everything — when
rulesexclude every job, not just aneeds:target. - Invalid CI config / YAML validation errors — a malformed
needs:block (wrong type, unknown keys) fails schema validation differently. Included file does not exist!— a brokenincludecan make the needed producer absent from the merged config.
Frequently Asked Questions
Why does GitLab say build was not added when it is clearly in my file?
Because GitLab validates needs: against the final set of jobs after rules/only/except and workflow are evaluated. If build is filtered out for the ref you are pushing, it is not “added to the pipeline,” even though it is defined in the file. Align the rules or mark the need optional.
How do I keep a deploy job that needs an optional build step?
Use needs: [{ job: build, optional: true }]. The consumer runs whether or not the producer is present, and only pulls the producer’s artifacts when it exists.
Can a job needs: another job in the same stage?
A needs: target must run in an earlier stage relative to the consumer for the dependency to be valid in the general case. The simplest fix is to move the producer into an earlier stage so it is unambiguously “prior.”
Why does my child pipeline fail to need a parent job?
needs: only works within a single pipeline. Parent and child are separate pipelines, so a child job cannot need a parent job. Pass data across the boundary with artifacts or a trigger, not needs:.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.