Why an Agent Applies One Fix to an Unrelated Bug
Quick answer: An agent applies a fix to an unrelated bug when similar symptoms or shared code let it attach the right change to the wrong location, often because the target was never pinned to a specific file and symbol. A green test run does not catch this on its own. Treating each change as single-purpose, locating the exact spot before editing, and reviewing every hunk against one root cause is what keeps a fix on target.
Why a fix lands on the wrong bug
The setup is usually more than one open problem. A session holds two failing cases, a couple of stack traces, and a handful of files that look alike. When the agent works from symptoms instead of a confirmed root cause, it reaches for the nearest code that resembles the failure. If two functions share a shape, or the same error message appears in two paths, the change that would fix bug A can be written against bug B's branch.
A second pressure is the drive to make the run pass. An agent is rewarded for a quiet build and green checks, so when its first edit does not clear the reported failure, it may extend the fix into adjacent code that was never part of the problem. The result is a diff that mixes a correct fix with an unrelated edit, and the unrelated half is easy to miss once the suite turns green.
The shapes this actually takes
For how these failures fit the broader agent workflow, see the AI coding agent guide. The drift itself takes a few recognizable shapes.
One common shape is the copied guard. The agent adds a null check or a timeout in every place that looks like the faulty one, including call sites that never hit the bug. Another is the global rename or replacement that corrects the target identifier and silently rewrites a second, valid usage. There is also the "while I'm here" change, where a refactor, formatting pass, or dependency bump rides along with the fix with no link to the failure.
| Signal in the diff | What it usually means | What to check |
|---|---|---|
| Same guard added in several files | Fix was broadened by resemblance | Whether every site can actually hit the bug |
| A rename or replacement beyond the failing path | Search-and-edit overreached | Whether the other usages were correct before |
| Formatting or refactor hunks mixed in | A "while I'm here" edit | Whether they belong in a separate change |
| Green tests with no new test for the bug | The fix may be unproven | Whether a test fails without the change |
How to keep a fix scoped to one bug
Pin the location before any edit. Ask for the file, symbol, and the exact line or branch where the bad value originates, and have the agent state the root cause in one sentence before it writes code. If that sentence cannot name a single cause, the target is not ready.
Add a test that fails on the bug and passes after the fix, then confirm the unrelated behavior is unchanged. Walk the diff hunk by hunk and ask of each one whether it serves the same root cause; anything that does not gets split out or dropped. Keep the change in one atomic commit so the extra edit can be removed without undoing the real fix. Powerduck's changes-only view and revision anchors make it easier to walk each hunk against that one cause instead of trusting a green run.
Frequently asked questions
If all tests pass, isn't the fix correct? Not for this failure. A green suite only shows the checked paths pass; it does not prove every edit was needed or aimed at the reported bug. Review the hunks even when the build is clean.
Should I let an agent fix several related bugs at once? Only when they share one confirmed root cause. Distinct symptoms that happen to look similar should be separate changes, each with its own test and commit.
How do I stop a broadened guard from coming back? Ask for the failing input before editing and require the agent to explain why each edited site can reach that input. A site with no path to the failure should not be touched.
The bottom line
A green run tells you the code works, not that the change is honest. Name one root cause, fix the exact location it points to, and treat every hunk that does not serve that cause as a separate decision. A fix that stays scoped is easier to review, safer to revert, and far less likely to create the next bug on an adjacent branch.