While many guides explain how to set up continuous integration pipelines, not many show you how to debug them when things go wrong across multiple layers.
This is a common experience when contributing to open source: you make a small change, open a pull request, and suddenly everything fails.
Not just one check, but several:
Lint errors
YAML validation issues
Create failures
Deployment failures
Even more confusing, you may see errors in parts of the codebase that you haven’t modified.
In this article, you’ll learn how to debug these issues step by step. The goal is not just to fix a pull request, but to understand how CI systems validate your changes.
This guide is based on actual debugging experience contributing to an open source documentation project.
While this example comes from a documentation project, the debugging workflow is applicable to many repositories that use CI pipelines, linting tools, and automated builds.
Table of Contents:
Conditions
To follow this guide, you must:
Understanding the CI Pipeline (What’s Really Happening)
In many projects, you’ll see the term CI/CD, which stands for Continuous Integration and Continuous Deployment (or Delivery).
In this guide, we will focus specifically on the CI part – namely, continuous integration. This refers to the automatic checks that run when you push code or open a pull request. These checks validate your changes before they are merged into the main code base.
CD (Continuous Deployment/Delivery), on the other hand, usually handles what happens after these checks are passed, such as deploying the application.
This distinction is important to understand because most of the issues we debug in this guide occur during the CI phase.
Most repositories run a number of automatic checks when you open a pull request:
Linting tools (eg, markdownlint, yamllint) enforces formatting rules.
Create systems (eg, mdBook) Validate the structure and generate the output.
Placement check (eg, Netlify) Make sure the site can be built and served.
Integrate controllers. (eg, Tide) enforces approval policies.
An important point to remember: CIs validate systems. The entire set of files in your commit, Not just the lines you changed.
How CI Pipeline Processes Your Pull Request
When you push code or open a pull request, the CI pipeline runs several checks in sequence.
Let’s imagine how these checks are connected in a typical CI pipeline.

Figure: A simplified CI pipeline showing how linting, building, and deployment checks are executed sequentially.
The diagram above shows a sequential CI pipeline with feedback loops, where failures at any stage return you to fix the problem before continuing.
Let’s break down what this diagram shows:
You start by pushing the code or opening a pull request.
The CI pipeline starts running automated checks.
The first set of checks usually involves linting tools such as markdownlint or yamllint.
If linting fails, the pipeline stops, and you must fix the formatting problems before continuing.
If the linting passes, the pipeline moves to the build phase (eg, mdBook in documentation projects).
If the build fails, it usually means there is a structural problem, such as duplicate entries or bad references.
After a successful build, deployment checks (such as Netlify previews) run.
- If deployment fails, the problem is often related to configuration or build output.
If all steps are passed, the bridge application is ready for review.
A practical debugging workflow
Step 1: Correct authentication and authorization issues.
Before CI runs, your push may fail due to authentication errors.
Example of error:
refusing to allow a Personal Access Token to create or update workflow
This happens because GitHub requires special permissions when your commit includes files:
.github/workflows/
The solution is to regenerate your Personal Access Token (PAT) with:
repoaccessworkflowpermission
Step 2: Run a lint check locally.
Relying only on CI feedback slows you down because you have to push changes and wait for the pipeline to run before seeing errors.
By running checks locally you can quickly catch problems before you push your code.
In practice, you should do both:
Think of native checks as the first line of defense and CI as the last gate before accepting your code.
Here’s an example (markdown inlining):
npm install -g markdownlint-cli2
markdownlint-cli2 docs/**/*.md
Step 3: Fix Common Markdown Lint Errors
Here are some common problems you may encounter:
1. Non-explanatory links
Non-descriptive links like “here” give the reader no context as to where the link leads. This makes documents harder to understand and less accessible, especially for users who rely on screen readers.
Instead of writing:
(here)(
Use descriptive text such as:
(command help documentation)(
2. Line length violations
Many projects enforce a maximum line length (often around 80 characters) to improve readability across different devices and editors.
If a line is too long, you can split it into multiple lines without changing the meaning.
To do this, break the line at natural points such as spaces between words or after punctuation. Avoid breaking up words or disrupting sentence structure.
For example:
This is a long sentence that should be split across multiple
lines to satisfy lint rules.
3. List the problems with indentation
List indentation errors occur when nested list items are not consistently aligned. This can break formatting and cause linting errors.
To avoid this, just make sure you use consistent spacing (usually 2 spaces per level).
Example (false):
- Item 1
- Subitem
Correct version:
- Item 1
- Subitem
Step 4: Validate the YAML within the Markdown code blocks.
YAML has strict formatting rules, including proper indentation, key-value structure, and constant spacing.
Even when YAML Markdown appears inside a code block, tools like yamllint validate its structure.
Example (false):
metadata:
annotations:
Correct version:
metadata:
annotations:
capi.metal3.io/unhealthy: "true"
In the wrong example, annotations Not down properly metadataand key-value pairs are not defined.
In the correct version:
This structure fulfills YAML’s need for proper classification and formatting.
Step 5: Fix build errors after lint passes.
Passing a lint check does not guarantee that your build will succeed.
This is because linting focuses on syntax and formatting, while the build process validates the structure and integrity of the entire project.
Construction failures are often caused by problems such as:
Duplicate entries in navigation files
Missing or misreferenced files.
Incorrect configuration settings
Even if your syntax is correct, the build system makes sure everything connects correctly.
For example, in documentation projects using tools such as mdBook, a duplicate entry SUMMARY.md Can still fail the build when all files pass the lint check.
Step 6: Debug cascading CI failures
CI pipelines are layered. A single failure can trigger multiple downstream failures.
For example, imagine a YAML indentation error:
YAML error → build fails → deploy fails → multiple checks fail
To fix it:
Identify the first step that failed in the CI logs.
Fix this problem.
Run the pipeline again.
In this example, a YAML indentation error is the root cause. After correcting the YAML formatting, the lint check passes, allowing the build to proceed and the deployment phase to succeed.
This is why it is important to always fix the first pipeline failure rather than trying to fix all the failures at once.
Step 7: Handle Git issues during CI debugging.
When working with updated branches, you may encounter:
Deflected branches.
Restore conflicts.
Push the rejections.
To resolve these issues, you generally need to update your branch using one of two methods:
Option 1: Rebase (Clear History)
git pull --rebase
Rebasing rewrites your commit history so that your changes appear on top of the latest version of the branch.
Use with caution:
Option 2: Merge (Save)
git pull --no-rebase
A merge preserves the full commit history and is safer when working with others, but it can introduce additional merge commits.
Push your changes securely
After updating your branch, you may need to make changes to:
git push --force-with-lease
Avoid using:
git push --force
gave --force The option may overwrite the work of other assistants. gave --force-with-lease option is safer because it only pushes if the remote branch has not changed unexpectedly.
Key takeaways
CI validates your entire commit, not just the specific lines you changed.
Linting and build systems implement different rules.
YAML within Markdown must be structurally correct.
Document builds may fail due to structural issues.
Running checks locally reduces debugging time significantly.
The result
Debugging a failed pull request isn’t just about fixing syntax errors.
You also need to understand how different systems interact:
Version control
CI Pipelines
Linting tools
Create an action
Once you understand how these systems work together, you can debug problems systematically rather than guessing.
The next time your pull request fails, you’ll know exactly where to start and how to fix it.
Debugging CI issues can feel overwhelming at first, but with a systematic approach, you can turn failures into a clear path to improvement.