What triggers a pipeline; when it is red
Intermediate
Why this matters
The pipeline is the gatekeeper on every change, and a red one blocks the merge button. Most failures are diagnosable in two minutes by anyone who knows where to look, whether or not they can read the code.
What starts a pipeline
The two that surprise people are the last two. A scheduled pipeline runs at a fixed time with nobody involved, which is the explanation for a failure at 03:00 that nobody caused, and it usually fails because something outside the repository changed. A manual run is started by a person from the interface, sometimes with different variables, which is why an identical commit can have both a red and a green run.
Rules in the configuration decide which jobs run for which trigger. This is why a merge request may run four jobs and a merge to main runs six: the deployment jobs are limited to the default branch (lesson 14.4).
The four-step diagnosis
- Find the failing job. The pipeline page says which; it does not say why. Open the job itself.
- Go to the end of that job's log. The last twenty lines almost always contain the cause. Everything above is setup.
- Find the first real error, not the last line. The last line is usually an exit code. The line you want is above it and names a file, often with a line number.
- Decide whether it is yours. Does it name a file you changed? Does the same job fail on
main? If it names something you never touched andmainis also red, it is not your change.
Step 4 is the one people skip, and it is what separates "I broke the build" from "the build was already broken", which are different conversations.
What the common failures look like
| Log says | Usually means | Fix |
|---|---|---|
docs/faq.md:31 MD001 … |
A linter rule | Fix that line; the rule name is searchable |
ModuleNotFoundError: No module named 'x' |
A dependency is not installed in the image | The dependency list needs it, or the job needs an install step |
No such file or directory |
A file was not committed, or a path differs | git status; check for uncommitted files |
Permission denied or 401 |
A token or variable is missing or expired | Ask; it is usually a project setting (lesson 9.12) |
ERROR: Job failed: exit code 1 alone |
The real error is above it | Scroll up |
Timed out or the runner disappeared |
Infrastructure | Retry, once |
Retrying
Retry when the failure was infrastructure: a timeout, a lost runner, a network error fetching a dependency. Do not retry when the log names your file, because the same code produces the same result.
A job that fails intermittently on unchanged code is flaky. Retrying it is a workaround, and it deserves an issue: flaky checks train a team to ignore red, which is how a real failure gets merged.
Asking for help usefully
When it is not yours to fix, four things make the question answerable in one reply (lesson 13.9):
- A link to the failing job, not to the pipeline.
- The error lines, pasted as text.
- What you already checked: "the same job is green on
main", "I ran the command locally and it passes". - What you changed, in one sentence.
That question gets an answer. "The pipeline is red, can someone look?" gets a queue.
The habit that prevents most of this
Read the configuration file and run its commands before pushing:
$ npx --yes markdownlint-cli "**/*.md" --ignore node_modules
$ python3 -m unittest discover -s tests -vTen seconds locally against ten minutes of round trip, and it works because the pipeline is running exactly those commands.
How to do it
$ cat .gitlab-ci.yml # what will run
$ git status # anything uncommitted that the runner will not see?With the platform's command-line tool installed, glab ci view or gh run view --log-failed reads the failing log without a browser.
The status bar shows the current branch's pipeline; the extension's tree opens a failing job's log in an editor tab, where the search box is better than the browser's.
The merge or pull request tool window lists the checks with their status and links to logs.
On the merge request, click the red icon to open the job. In the job, use the log search, the raw-log link for long output, and Retry for infrastructure failures. Build → Pipeline schedules explains a run nobody triggered.
On the pull request, the Checks tab; expand the failed step and read upwards. Re-run failed jobs and Re-run with debug logging are in the run's menu. The Actions tab shows scheduled runs.
Common mistakes
- Reading only the last line of a log.
- Retrying a real failure, repeatedly.
- Assuming red means you broke it. Check
main. - Pushing repeatedly to test a fix. Run the command locally.
- Reporting "the pipeline is red" without a link to the job or the error text.
- Ignoring a flaky job rather than raising it.
Try it yourself
Goal: diagnose a failure you caused, and one you did not.
- On a branch, introduce a linter error in a Markdown file. Push and open a merge request.
- Use the four-step method: find the job, go to the end of the log, find the real error, decide whether it is yours.
- Fix it and push.
- Now check whether the same job passes on
main, so you know what "not mine" looks like. - Write the question you would ask if the failure had not been yours, with a link, the error text and what you checked.
Expected result: one diagnosis, one fix, and a written question you could send without editing.
Show solution
Step 4 is the comparison that makes step 5 possible. Knowing the state of main turns "something is broken" into "this job is failing on main as well, so my change is not the cause", which is the single most useful sentence in a CI conversation.