DEV Community

Cover image for Why does my CI keep failing? (and how to stop guessing)
ci why
ci why

Posted on

Why does my CI keep failing? (and how to stop guessing)

Every developer knows this moment.

You push a commit. CI runs. It fails. You open the log and stare at 400 lines of output trying to find the one line that actually matters.

Ten minutes later you're still scrolling.


Why CI logs are so hard to read

CI runners don't write logs for humans. They write them for machines. Everything gets dumped — timestamps, progress bars, ANSI escape codes, dependency install output, test runner boilerplate — and somewhere buried in all of it is the actual error.

The problem isn't that CI is broken. The problem is that the signal is buried under noise.


The most common reasons CI fails

1. A test is failing
Someone changed code that broke an existing test, or a mock is returning the wrong value. The error is in there — you just have to find it.

2. A dependency version conflict
Your CI runner is on a different version of Node, Python, or another runtime than your local machine. Works on your laptop, fails in CI.

3. An environment variable is missing
A secret or config value exists in your local .env but wasn't added to your CI secrets. The app crashes on startup.

4. A timeout
A test or build step is taking too long and CI kills it. The log just says "Process killed" with no explanation.

5. A flaky test
A test that passes 95% of the time but fails randomly due to timing, network, or order-of-execution issues.


The slow way vs the fast way

The slow way is what most developers do — scroll the raw log, Ctrl+F for "error", guess what went wrong, push a fix, wait for CI to run again, repeat.

The fast way is to pipe your log through ci-why:

cat build.log | ci-why
Enter fullscreen mode Exit fullscreen mode

It strips all the noise, sends the relevant parts to Claude, and prints back a plain English explanation:

──────────────────────────────────────────────────
  WHY
  The authentication service returns null for the token field
  instead of a valid string, causing the test assertion to fail.

  FAILING LINE
  src/services/auth.test.ts:63

  SUGGESTED FIX
  Check authService.login() in auth.ts — it's returning
  {"token": null} for valid credentials.
──────────────────────────────────────────────────
Enter fullscreen mode Exit fullscreen mode

Instead of reading 300 lines, you read 8.


How to set it up

npm install -g ci-why
ci-why setup
Enter fullscreen mode Exit fullscreen mode

The setup wizard walks you through getting a free Anthropic API key and saves it automatically. Takes about 2 minutes.

Then any time a build fails:

# Pipe directly
cat build.log | ci-why

# Or point at a file
ci-why ./logs/build.log

# Get JSON output for scripting
ci-why --json ./build.log
Enter fullscreen mode Exit fullscreen mode

It works with Jest, pytest, Go test, Rust/Cargo, and Maven — auto-detected from your log.


Works in GitHub Actions too

Add it to your workflow and it automatically posts a plain English explanation as a PR comment every time a build fails:

- name: Explain failure with ci-why
  if: steps.build.outcome == 'failure'
  uses: ciwhy-tool/ci-why@v0.2.0
  with:
    log-file: /tmp/build.log
    anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}
    github-token: ${{ secrets.GITHUB_TOKEN }}
    pr-number: ${{ github.event.pull_request.number }}
Enter fullscreen mode Exit fullscreen mode

Every developer on your team sees the explanation — not just the one who installed the tool.


Free and open source

ci-why is completely free. You bring your own Anthropic API key (free to get, costs fractions of a cent per run).

npm install -g ci-why
Enter fullscreen mode Exit fullscreen mode

GitHub: github.com/ciwhy-tool/ci-why


Tags: devops, node, testing, productivity, opensource

Top comments (0)