Delivery & operationsBeginner

When Your CI Pipeline Fails

Read the failing step, separate code problems from environment differences, and use the smallest experiment that explains a red pipeline.

8 min readDelivery & operations
In this guide 7 sections

A red CI check means a configured command did not complete successfully in the runner environment. It does not tell you yet whether the code is wrong, the environment differs, a dependency service is missing, or the workflow itself is misconfigured.

Use the run’s job and step logs to locate the first failing command. GitHub Actions records logs by job and step, so the visible summary is a map to the evidence, not a diagnosis on its own.

A quick decision tree

Did the workflow start?
├─ No → Check trigger conditions, workflow syntax, permissions, and skipped status.
└─ Yes → Which first command failed?
   ├─ Install / download → Check lockfile, registry access, cache, and runtime version.
   ├─ Test / type check → Compare code, fixtures, time, locale, and runtime inputs.
   ├─ Database / service → Confirm the service starts and is healthy before the test.
   ├─ Build → Inspect required variables, generated files, and exact build output.
   └─ Deploy / publish → Check credentials, target environment, and provider output.

The first failure matters because later steps may fail only because earlier setup did not finish.

Read the failure in order

  1. Open the failed job and identify the first red step.
  2. Read a few lines before and after the first error. Look for the exact command, exit code, runtime version, and service names.
  3. Check whether the step was skipped, canceled, timed out, or actually failed. Those states have different causes.
  4. Compare the workflow file and lockfile with the commit being tested. A local uncommitted fix cannot explain a remote run.
  5. Reproduce the command locally when the environment permits it. Record what is different before changing anything.

Illustrative failure: the code is not the first problem

Run npm test
Error: connect ECONNREFUSED 127.0.0.1:5432
  at openDatabase (test/helpers/database.ts:18:11)

It is tempting to blame the latest database query. First inspect whether the test job starts its database service and waits for it to become healthy. If the service is missing or not ready, the application code has not yet been meaningfully tested. Reproduce with the same database version and setup rather than changing the query.

If the database is running, check the next evidence: connection host, port, credentials, schema setup, and whether the failing test is order-dependent. Change one thing, rerun the focused test, and keep the original log for comparison.

Common cause groups

Log points toCompare first
Install or module resolutionNode/package-manager version, lockfile, registry, cache key
Test assertionTest data, timezone, locale, randomness, concurrency, missing fixture
Connection refusedService container, port mapping, startup health check
Missing variableWhether the variable belongs in CI, or the test should use a safe fixture
Permission deniedFile mode, runner user, token scope, repository permissions
TimeoutActual runtime, deadlock, external dependency, insufficient readiness wait

Do not fix a missing test variable by copying a production secret into a workflow. Determine whether it is safe and necessary for a test; prefer a non-sensitive fixture or mock when possible.

Ask AI for hypotheses, then test them

You can paste a redacted log excerpt and the relevant workflow step into an approved coding assistant. Ask for a short ranked list of hypotheses and a command or observation that would distinguish each. Do not include credentials, user records, private source code outside approved tools, or unrestricted CI logs. Treat the answer as a proposal. The log and a discriminating experiment provide evidence.

After the fix

  • Re-run the narrow command and the full CI job when practical.
  • Check that the fix addresses the cause and does not hide the failure with retries or skipped tests.
  • If the runner environment was wrong, fix its setup and document any required service or variable.
  • Share the failing step, root cause, and verification in the pull request.

Practice

Pick a CI failure from a project you can safely inspect. Write down: first failing step, exact error, local command to reproduce, one environmental difference, and the next experiment. Ask someone else whether your experiment would distinguish the top two hypotheses.

CI TRIAGEChoose your move

The database test cannot connect

CI fails with `ECONNREFUSED 127.0.0.1:5432` at the first database test. The same test passes locally. What do you inspect first?

FIELD
TEST
TAKE IT WITH YOU

The pocket checklist

0/4

Use these as a quick pre-flight check next time you're doing the work. Checked items stay saved on this device.

Your checklist and saved guides stay in this browser. Nothing is sent to a server.

SOURCES & FURTHER READING

Keep exploring

These references support the concepts in this guide. Tool-specific details can change; check the current documentation when applying them.