Quick reference
Diagnose — Read the log, top to bottom
- Open the failed step — The red step, not the whole job. The error is there.
- Reproduce locally — Run the exact command on your machine.
- Check the runner — ubuntu-latest can differ from your laptop.
Fix — The usual causes
- Lockfile out of sync — Commit
package-lock.json. npm ci needs it exact. - Missing secret or env — Set it in repo Settings > Secrets, not in code.
- Wrong versions — Pin node/python versions in the workflow.
Prevent — Fewer red X's
- Pin action versions — uses: actions/checkout@v4, not @main.
- Cache dependencies — Faster, and fails less on network blips.
- Run the same checks locally — pre-commit hooks catch it before CI.
Explained
Diagnose
Open the failed step, not the whole job. GitHub Actions marks the exact step that failed in red. Expand it and read the last 20 lines; the real error is almost always there, above the generic "exit code 1". Reproduce locally. Run the exact command from the workflow on your machine. Most failures reproduce immediately, and local debugging is far faster than pushing commits to re-trigger CI. Check the runner. ubuntu-latest is not your laptop. Different OS, different default versions, a clean checkout with no local files. Many "works on my machine" failures live here.
Fix
Lockfile out of sync. npm ci (and its equivalents) demand that the lockfile matches package.json exactly. Commit the updated package-lock.json. Missing secret or environment variable. Set it in the repository's Settings, Secrets, not in the code, and reference it in the workflow. A blank secret is a common silent failure. Wrong versions. Pin the Node or Python version in the workflow so CI matches what you tested.
Prevent
Pin action versions: uses: actions/checkout@v4, not @main, so an upstream change cannot break your build overnight. Cache dependencies, which makes runs faster and less fragile on network hiccups. Run the same checks locally with pre-commit hooks, so most failures never reach CI.
The habit: read the failed step first. The log already told you what broke.
In one line
The log already told you. Open the failed step, read the error, reproduce it locally.
The first move: open the red step and read the last 20 lines
More notes: Git & CI/CD
Open in the notes app: search, filters, copy This note on GitHub