You’ve been staring at the same line of code for an hour. It looks correct. Your teammate walks over, glances at the screen, and says, “Shouldn’t that be ‘===’ instead of ‘==’?” You feel a mix of embarrassment and disbelief. How did you miss that?
This experience is so common it has a name: bug blindness. It’s not a sign of incompetence. It’s a cognitive phenomenon that affects even the most experienced developers. Understanding why it happens—and what to do about it—can save you hours of frustration and prevent bugs from reaching production.
What Is Bug Blindness?
Bug blindness is the inability to see obvious errors in your own code after working on it for a while. It’s a specific form of habituation: your brain gets so used to what you’ve written that it stops truly seeing it. Think of it like hearing a clock tick in your living room. After a few minutes, you don’t notice it anymore. Your brain filters out the constant stimulus. Similarly, when you read your code over and over, your brain fills in what it expects to see, not what’s actually there.
The term was popularized by Dan Luu in his essay “Bug Blindness,” where he argues that this is not just a personal failing but a systemic problem. It’s built into how we work: long hours in front of a screen, massive code changes, and tools that don’t give us the context we need.
The Psychology Behind the Blindness
Bug blindness draws on well-known cognitive biases. One is inattentional blindness—the same phenomenon demonstrated in the famous “invisible gorilla” experiment, where people watching a basketball game fail to notice a person in a gorilla suit walking through the scene. When you’re focused on one thing (like making your code work), your brain literally doesn’t process other information (like a typo that causes a bug).
Another factor is confirmation bias. Once you believe your code is correct, you unconsciously look for evidence that supports that belief and ignore anything that contradicts it. You read what you meant to write, not what you actually wrote.
Then there’s satisfaction of search. If you’re reviewing your own diff and you spot one small issue, you feel a sense of relief and think, “I’ve found the problem.” That feeling makes you less likely to keep looking for other issues. Your brain says, “Good enough, we’re done here.” This is why even a thorough self-review often misses more than one bug.
Why Code Review Often Fails
You might think, “That’s why we have code review.” But here’s the catch: code review often falls prey to the same blindness. Reviewers are often familiar with the codebase and the author’s style. They’ve seen similar code many times. They might also be in a hurry, with their own work piling up.
Luu’s essay points out that reviewers are especially ineffective when the diff is huge. If a pull request touches 50 files, a reviewer can’t give each one the same attention. They’ll skim, they’ll focus on the parts they understand, and they’ll miss the subtle bug that’s hiding in a file they’ve seen a hundred times.
But even with small diffs, reviewers can be blind. If they’ve been reviewing the same type of code all day, their brains start to gloss over details. The result is that code review becomes a rubber stamp rather than a safety net.
The problem is compounded by poor tooling. Many diff tools show only the changed lines, ripping them out of context. You can’t see the surrounding function, the variable names, or the logic flow. This makes it harder to spot inconsistencies. If the tool highlighted the whole function or showed the before-and-after in a meaningful way, bugs would be more obvious.
Feedback Loops: The Antidote
One of the most powerful factors in avoiding bug blindness is the speed of feedback. The longer the delay between writing code and seeing it fail, the more likely the bug will persist. When you write a line of code and run the test five seconds later, you catch a typo immediately. But if you write code and don’t test it until the next day, or if the test suite takes 20 minutes, you’ve lost that tight loop. Your brain has already moved on, and the bug becomes invisible.
This is why test-driven development (TDD) can be effective. Writing the test first forces you to think about behavior, and the immediate red-green cycle keeps you in a tight feedback loop. You see the test fail, so you know the code is broken. You see it pass, so you know it works. The feedback is clear and immediate.
Similarly, property-based testing can catch classes of bugs that human eyes miss. Instead of checking one example, it generates hundreds of random inputs and verifies that a property holds for all of them. If your function is supposed to be commutative, it tests that a + b equals b + a for many random values. This is a way of getting feedback that doesn’t rely on human vigilance.
The Role of Tools and Language
Some languages and tools are better at preventing bug blindness than others. Static typing, for example, catches certain errors before you even run the code. If you pass a string to a function that expects an integer, the compiler stops you. Strong linters can flag potential issues like unused variables or unsafe operations. These tools act as an external check that doesn’t suffer from cognitive bias.
Luu’s essay implicitly criticizes environments that rely too heavily on human vigilance. In dynamic languages like Python or JavaScript, there’s no compiler to catch a typo in a variable name. The error might not show up until runtime, and if you’re not testing that path, you might not see it for weeks. In a statically typed language like Rust or Haskell, many of these bugs are caught immediately.
The lesson isn’t that you must use a statically typed language, but that you should use whatever tools are available to move the feedback loop earlier. A linter that catches a potential bug is worth more than a hundred self-reviews.
What Actually Works: Practical Strategies
So, what can you do to combat bug blindness? Here are strategies that have real evidence behind them:
1. Shrink your diffs. If you’re working on a feature that will take a week, don’t wait until Friday to open a pull request. Break it into smaller, mergable pieces. Smaller diffs are easier to review, and you get feedback sooner. This also reduces the cognitive load on the reviewer.
2. Use checklists. A structured code review checklist can force you to look for specific types of bugs. For example, “Check all boundary conditions” or “Verify error handling.” This prevents satisfaction of search because you’re systematically going through a list rather than scanning until you find one thing.
3. Get fresh eyes. If a change is critical, ask someone who hasn’t been involved to look at it. A new person doesn’t have the same assumptions and will notice things you’ve tuned out. This is often more effective than asking a colleague who works on the same code daily.
4. Change your perspective. If you’re reviewing your own code, try reading the diff in reverse order, or change the font size. This might sound silly, but it disrupts your brain’s pattern-matching and can make bugs pop out. Even taking a walk and coming back with fresh eyes can help.
5. Invest in automated testing. The best defense is to have tests that fail when a bug exists. Aim for high coverage on critical paths, and use property-based testing where feasible. A suite of good tests is like having an army of fresh-eyed reviewers that work 24/7.
The AI Question: Can Copilot See What You Miss?
Given the buzz around AI pair programmers, you might wonder if they can solve bug blindness. The short answer is: sometimes. AI tools like GitHub Copilot can act as a second pair of eyes, catching things like null pointer exceptions or off-by-one errors. They don’t get tired or bored.
But there’s a catch: automation bias. If you trust the AI too much, you might stop paying attention. And AI can also hallucinate—suggesting a fix that looks plausible but is wrong. The same confirmation bias that affects human review can affect how you evaluate AI suggestions. If the AI says your code looks fine, you might be even more confident it’s correct, reinforcing your blindness.
The evidence is mixed. Some developers report that AI catches bugs they missed, especially in unfamiliar languages. Others find that it misses context-specific bugs or suggests changes that break other parts of the code. Treat AI as a helpful advisor, not an infallible oracle.
What Managers Need to Know
If you’re a team lead or engineering manager, bug blindness should be a process concern, not a personal one. When a bug slips through, don’t ask, “Who wrote this?” Ask, “What in our process allowed this to happen?” Was the diff too large? Was there no test for that path? Was the review done in a rush?
Blameless post-mortems can reveal systemic issues. For example, if you find that bugs often come from last-minute changes, you might introduce a rule: no changes after code review has started. If you find that certain files are notoriously buggy, you might invest in refactoring or adding more tests.
One key takeaway is that “move fast and break things” is fine for a startup, but not for a hospital or an airline. In high-assurance domains, you need stricter processes: mandatory fresh-eye reviews, formal verification, and extensive testing. The cost of a bug is too high to rely on human attention alone.
The Fresh Eyes Ideal
Organizations rarely structure workflows to leverage fresh eyes effectively. Often, the same people who wrote the code are the ones who review it. They’re too close to the work. A better approach is to have a rotating role of “reviewer” who is not part of the feature team. Or, for critical changes, bring in someone from a different team who has a fresh perspective.
This is easier said than done. It requires time and resources. But if you consider the cost of a bug that makes it to production—the debugging time, the user frustration, the reputation damage—a little extra review structure is worth it.
A Balanced View
Some skeptics argue that bug blindness is overblown. They say most bugs are not missed because of blindness but because of insufficient testing or poor requirements. That’s true to an extent. If you don’t have a test for a feature, no amount of staring at code will catch a logic error. If the requirements are ambiguous, you might implement the wrong thing, and no review will catch that if the reviewer has the same misunderstanding.
But that doesn’t negate bug blindness. It’s a real phenomenon that contributes to bugs. The solution is not to blame developers but to build systems that account for human limitations. That means better tools, tighter feedback loops, and smarter review processes.
Conclusion
Bug blindness is a natural consequence of how our brains work. It happens to everyone, from junior devs to principal engineers. The key is to recognize when it’s happening and to have strategies in place to counter it. Shrink your diffs, write tests, get fresh eyes, and use tools that catch what your brain can’t. By designing your workflow around this cognitive limitation, you’ll catch more bugs before they reach production—and save yourself a lot of embarrassment.
The next time you miss an obvious bug in your own code, remember that it’s not a personal failing—it’s a cognitive quirk that affects everyone. The best response is not to try harder but to change your approach. Build feedback loops that catch issues early, seek out fresh perspectives, and rely on automated tools to be your tireless second pair of eyes. That’s how you beat bug blindness.
Summary
- Bug blindness is a cognitive phenomenon, not a sign of stupidity. It stems from habituation and confirmation bias.
- Code review often fails because reviewers suffer from the same blindness, especially with large diffs.
- Tight feedback loops are the best defense: write tests, use type systems, and get feedback quickly.
- Practical strategies include smaller diffs, review checklists, and fresh-eye reviews.
- AI tools can help but aren’t infallible; beware of automation bias.
FAQ
Q: Is bug blindness the same as being careless?
A: No. It’s a normal cognitive limitation that affects even the most careful developers. Your brain filters out what it expects to see, so you miss errors that are obvious to someone else.
Q: Why doesn’t code review always catch bugs?
A: Reviewers are often familiar with the code and can be blind to the same issues. Large diffs and poor tools make it worse. The most effective reviews are focused, structured, and done with fresh eyes.
Q: How can I reduce bug blindness in my own code?
A: Take breaks, review your code in a different order, change the display, and write tests that verify behavior. The key is to disrupt your brain’s pattern-matching.
Q: Can AI pair programmers eliminate bug blindness?
A: They can help, but they’re not perfect. They may miss context-specific bugs or suggest wrong fixes. Also, trust in AI can make you less vigilant. Use them as a supplement, not a replacement, for good practices.
Q: What can managers do to help their teams avoid bug blindness?
A: Encourage smaller merges, invest in automated testing, provide review checklists, and structure workflows so that critical changes get fresh eyes. Focus on process improvements, not blame.

Leave a Reply