Est.

Why I Didn't Block Every Merge on 35 Pre-Existing Type Errors

Blocking on pre-existing errors would have destroyed adoption of the new CI pipeline.

· 2 min read
Features · September 24, 2026 · 2 min read · 398 words
# Why I Didn't Block Every Merge on 35 Pre-Existing Type Errors Standing up the first CI pipeline for an inherited codebase, the obvious move is to add a build gate and a typecheck gate and require both green before anything merges. I added the build gate. I made the typecheck gate deliberately non-blocking, and that was the right call — but it's worth explaining why, because "don't gate on the type errors" sounds like cutting a corner until you look at what was actually in the codebase. ## What the audit found The inherited application carried roughly 35 pre-existing TypeScript errors, accumulated over however long the codebase had gone without a working CI pipeline at all. None of them were newly introduced — they were baseline debt, present before I touched anything, scattered across files with no clean way to fix all 35 without a dedicated pass that had nothing to do with whatever the next feature branch actually needed to ship. ## The actual choice A hard-blocking typecheck gate on day one means the first PR after CI goes live can't merge — not because it's wrong, but because it happens to touch a file with a pre-existing, unrelated error. That trains people to route around the gate, disable it, or add sweeping ts-ignore comments just to get unstuck, which is worse than not having the gate. So I split the two: the build gate blocks, because a build that doesn't compile is an unconditional problem. The typecheck gate runs and reports, visibly, but doesn't block — so the 35 existing errors are tracked and visible without holding every unrelated change hostage to a cleanup that hadn't happened yet. ## What this is actually a bet on This is a gate placed at the achievable bar, not the ideal one, with a plan to tighten it later once the baseline is paid down rather than pretending the baseline doesn't exist. A CI setup that can't be adopted because it's too strict for the code it's protecting isn't stricter in practice — it's just off, because someone will disable it under deadline pressure. Gating on what a team can actually hit gets you a gate that survives contact with a real deadline; gating on the ideal gets you a gate that gets bypassed the first time it's inconvenient, which is strictly worse than never having shipped it.

More in Features