When a CI/CD pipeline fails, the fastest path to a fix is a disciplined diagnosis rather than repeated reruns. This reusable checklist helps you isolate failed tests, dependency and environment problems, permissions and secrets errors, cache issues, flaky jobs, and deployment failures across common CI/CD platforms.
Overview
A pipeline failure is a symptom, not a diagnosis. The visible error may appear in a test step while the underlying cause is an incorrect working directory, a missing service, an expired credential, a changed dependency, or a difference between the runner and the development environment.
Use this order when you need to debug CI pipeline failures:
- Preserve the evidence. Save the run URL, commit or revision, failed job, relevant logs, and any recent workflow changes.
- Find the first meaningful error. Later messages often describe cascading failures rather than the original problem.
- Classify the failure. Decide whether it is related to code, dependencies, configuration, infrastructure, credentials, timing, or deployment state.
- Reproduce the smallest failing step. Run the same command locally or in an equivalent container, using the same versions and inputs where possible.
- Change one variable at a time. A focused experiment produces more useful evidence than several unrelated edits.
- Record the fix. If the failure could recur, update the workflow, documentation, test, alert, or runbook rather than relying on memory.
Before changing pipeline logic, check whether the failure is isolated to one revision, branch, runner, environment, or service. Comparing a failed run with the last successful run is often a more reliable starting point than reading the entire log from top to bottom.
Checklist by scenario
1. Failed tests
- Identify the exact test file, case, assertion, and input that failed.
- Check whether the failure is deterministic by rerunning the same test or job once with the same revision.
- Compare test commands, runtime versions, operating system, locale, timezone, and environment variables with the local setup.
- Look for shared state: temporary files, databases, queues, ports, browser profiles, or test records that are not cleaned up.
- Check whether tests run in parallel and accidentally depend on execution order or a shared resource.
- Separate an assertion failure from a test-setup failure. A service that never started is a different problem from an incorrect application result.
If the same test passes locally but fails in CI, do not immediately label it flaky. First compare the inputs and runtime assumptions. A temporary quarantine may be appropriate for a genuinely flaky test, but it should include an owner, a reason, and a follow-up date.
2. Dependency installation and build errors
- Confirm that the pipeline uses the intended package manager and lockfile.
- Check runtime, compiler, package-manager, and operating-system versions.
- Read the first package-resolution or compilation error, not only the final nonzero exit message.
- Verify registry URLs, authentication settings, proxy configuration, and network access.
- Check whether a transitive dependency changed because the lockfile was absent, ignored, or regenerated.
- Confirm that native modules have the required compiler, system library, or architecture support on the runner.
- Run a clean installation without the cache to distinguish a corrupted cache from a reproducible dependency problem.
Lockfiles, explicit tool versions, and reproducible build commands reduce ambiguity. For containerized builds, review the base image and build context as carefully as the application code. The Docker build cache optimization checklist is useful when cache behavior is contributing to slow or inconsistent builds.
3. Secrets, credentials, and permission errors
- Check whether the required secret or variable is available in this repository, branch, event type, and environment.
- Distinguish an unset value from an invalid value. Log variable names and presence checks, never secret contents.
- Verify that the identity used by the job has the minimum permission required for the action.
- Check token scope, expiration, audience, region, account, project, and target environment.
- Confirm that protected environments or approval gates are not preventing the job from receiving credentials.
- Review recent rotation, repository transfer, organization, or cloud-account changes.
A masked value can still be misconfigured. Treat a credential error as a configuration and identity problem, not as a reason to print more diagnostics. For broader design decisions, see the secrets management comparison.
4. Environment mismatch and service failures
- Compare the CI environment with local and staging environments, including operating system, architecture, timezone, locale, and shell.
- Verify that required databases, queues, browsers, containers, or emulators are running before tests begin.
- Check service hostnames and ports. A service may be reachable locally through a different network path than it is from the runner.
- Confirm startup order and add a readiness check rather than relying on a fixed sleep.
- Check resource limits, disk space, memory, and process limits when jobs terminate unexpectedly.
- Record versions of external services used by the job where reproducibility matters.
Environment validation belongs near the start of the job. A short diagnostic step that prints safe version and connectivity information can prevent a long, misleading test log.
5. Flaky jobs and timeouts
- Compare failures by test, runner, branch, time of day, dependency, and execution duration.
- Look for race conditions, unbounded retries, shared resources, asynchronous cleanup, and time-sensitive assertions.
- Check whether the job is waiting on a service that is slow to become ready.
- Use a bounded retry only when the operation is safe to repeat and the underlying condition is understood.
- Capture diagnostics on timeout: process lists, service status, recent logs, and resource usage.
- Track quarantined tests separately from passing tests so instability does not become invisible.
A retry can improve signal for an external, transient failure, but retries can also hide a real regression. Define what the retry is protecting against and when the job should still fail.
6. Deployment failures
- Confirm that the artifact was built successfully, identified unambiguously, and is available to the deployment job.
- Verify target account, region, cluster, namespace, project, and environment before making another attempt.
- Check deployment identity permissions and the configuration values supplied to the target.
- Inspect rollout status, health checks, events, logs, and resource availability.
- Determine whether the failure occurred before rollout, during rollout, or after traffic shifted.
- Use the documented rollback path when the release could affect users or data.
For higher-risk releases, pair this troubleshooting process with the pre-deployment checklist. If the delivery model is GitOps-based, also review the differences between Argo CD and Flux when diagnosing reconciliation or drift-related behavior.
What to double-check
Before declaring a pipeline fixed, work through these final checks:
- Revision: Are you debugging the same commit, merge result, or generated configuration shown in the failed run?
- Inputs: Did the rerun use the same branch filters, variables, secrets, artifact, and deployment target?
- Workflow syntax: Are conditions, dependencies, matrix values, working directories, and shell behavior what you intended?
- Permissions: Did the job succeed because a broad temporary permission was added? Replace it with the smallest durable permission.
- Cache: Can stale dependencies or build outputs return after the next key change? Ensure cache keys include the inputs that matter.
- Observability: Does the job expose enough safe context to diagnose the next failure without revealing credentials?
- Rollback: If deployment completed partially, is the system in a known state and is rollback or forward repair documented?
- Verification: Did you test the actual failure path, not only a nearby successful path?
For infrastructure-related failures, distinguish a pipeline error from configuration drift in the target environment. The Terraform drift detection checklist can help when declared and actual infrastructure no longer agree.
Common mistakes
- Rerunning without recording evidence: A successful rerun may remove the clues needed to understand a transient failure.
- Reading only the last line: Exit codes summarize a job; they rarely identify the cause.
- Changing several things at once: This makes it difficult to know which change corrected or concealed the problem.
- Printing secrets for debugging: Use presence checks, safe metadata, and redacted diagnostics instead.
- Using unlimited retries: A green pipeline that silently retries real failures weakens release confidence.
- Assuming local parity: “It works on my machine” often indicates an unrecorded version, service, filesystem, or environment difference.
- Ignoring failed cleanup: Resource leaks can make later jobs fail and mislead the investigation.
- Fixing the symptom in the pipeline only: If the application, test, dependency, or infrastructure is the source, document and address that layer.
When a failure has caused repeated disruption, create a short postmortem with the trigger, impact, contributing conditions, corrective action, and owner. A postmortem action item tracker can help turn recurring pipeline problems into completed reliability work.
When to revisit
Revisit this CI/CD failure checklist whenever the workflow or its inputs change. That includes moving to a new runner image, upgrading a language or package manager, changing cache keys, adding a deployment target, rotating credentials, modifying branch protections, introducing parallel jobs, or replacing a build or deployment tool.
It is also worth reviewing before seasonal planning cycles or major release periods. Look for recurring failure categories, jobs with long or unstable durations, obsolete workarounds, missing ownership, and steps that require manual intervention. Confirm that the documented rollback procedure still matches the delivery workflow.
For the next failure, use this practical sequence:
- Open the failed run and save its revision, job, timestamp, and URL.
- Locate the first actionable error and classify the scenario.
- Compare the failed run with the last successful run.
- Reproduce the smallest failing command with equivalent inputs.
- Apply one controlled fix, then rerun the relevant validation.
- Document the cause and add prevention if the failure is likely to recur.
A pipeline is easier to operate when its failures are specific, observable, and recoverable. Treat each incident as feedback about the workflow’s design, not only as a task to make the latest run green.