Skip to content
cd /blog

Why your AI coding agent hallucinates file paths

[AI Agents] [Hallucination] [Retrieval] [MCP]

> AI coding agents invent file paths when they have no real map of the repo. Here is why it happens, and how grounding leads to fewer hallucinated edits.

The tell is not a wrong function body. It is a confident edit to a file that does not exist, or to a file that exists but is not the one that implements the behavior.

You asked for a session-expiry fix. The agent opened src/auth/session.ts. That path is plausible. It is also wrong. The real handler lives in apps/api/src/middleware/expiry.ts, renamed two refactors ago. The agent did not lie to you. It completed a path-shaped string from training priors plus whatever was already in the context window.

This is the common failure mode on a real repository. The model can write code. The miss is choosing the wrong place to write it.

Why agents invent paths

A coding agent is a next-token model with tools. When you say “fix session expiry”, it has to name a file before it can read or patch anything. If it does not already have a grounded map, it constructs a path from:

  1. Naming conventions it has seen in other repositories. src/auth/session.ts is a frequent shape.
  2. Files already in the conversation, which may be the ones you pasted last week, not the ones that matter now.
  3. Directory listings it happened to run, which are incomplete on a large tree.
  4. Instruction files. CLAUDE.md and AGENTS.md tell the agent how to behave. They are not a live index of symbols, callers, or current paths.

None of those sources is a map of this repo, today. The model fills the gap the way it fills any gap: with a high-probability continuation. That continuation often looks like a real path. Sometimes the file exists and is adjacent to the right one. Sometimes it existed on a branch that merged last month. Sometimes it never existed.

Grep does not save you here if the agent never searches for the right string. The agent guessed a path, then read whatever that path returned, then edited it. The first wrong step was the path, not the patch.

Reading files is also not the same as finding the right ones. Claude Code, Cursor, Codex, and similar tools can open whatever you point them at. The question is whether they reliably find the right files, the important symbols, the dependencies, the tests, and the blast radius before they edit. File access without a map still starts with a guess.

The wrong-file edit is a retrieval problem

Treat the invented path as a retrieval miss, not a personality flaw.

If the agent had to return path/file.ext:line before it was allowed to edit, two things would happen. First, you could open the citation and reject the work in ten seconds. Second, the agent would have to query something that actually knows the tree.

That is the job of a codebase context layer. Semantic search alone is not enough. A chunk that “sounds like session expiry” can still land in a deprecated package. You also need exact text when you know the string, symbol lookup when you know the name, structural search when you know the shape, and a dependency graph when you need callers and blast radius.

Maguyva is that layer for MCP-compatible coding agents. It is not an editor. Claude Code, Cursor, Codex CLI, VS Code, Windsurf, and other MCP clients stay where they are. The agent queries a ranked map before it touches a line.

The claim is modest on purpose: fewer hallucinated edits. Maguyva does not remove the model’s ability to guess. It changes the default first step from “invent a plausible path” to “ask for ranked, cited locations.”

What a grounded answer looks like

A useful answer to “where is session expiry handled” is not a paragraph. It is a short list of locations:

  • apps/api/src/middleware/expiry.ts:48 - the handler
  • apps/web/src/lib/auth-client.ts:112 - the caller
  • apps/api/tests/expiry.test.ts:20 - the test that will fail if the change is wrong

You can open those lines. If they are wrong, you stop. If they are right, the agent may edit. The verification is the point, not a slogan.

Maguyva exposes 11 customer-facing MCP tools across search, symbols, dependency analysis, file retrieval, repository context, and deterministic utility workflows. Four retrieval modes (semantic, structural, graph/dependency, and text) are fused into ranked results; symbol lookup is a separate MCP tool (find_symbol). Grounded answers come back with file paths and line numbers so you can grade them against the tree in front of you.

The docs describe the shortest path: start free, index a repo you already know, connect the client, then ask one question you can verify.

A loop that changes the first edit

You do not need a new workflow religion. You need one extra step before the first write.

  1. Ask a question you can already grade. “What code handles login and session expiry?” is better than “fix auth.”
  2. Demand citations. File path and line number, not a summary of “the auth module.”
  3. Open the cited files. Follow the symbol. Confirm the dependency you are about to break.
  4. Only then let the agent patch.

If step 2 returns nothing useful, the agent does not get to improvise a path. It searches again, or you point it. That single gate is what produces fewer hallucinated edits. The model is the same model. The map is what changed.

Instruction files still matter. Keep them. Use them for conventions, review rules, and what not to touch. Do not ask them to be the index. A CLAUDE.md that lists three important directories will be stale the week after a package split. A queryable map updates when the repo updates.

A related failure is the near-miss file: the agent opens auth.ts when the behavior lives in auth-client.ts, or patches a generated file instead of the source, or edits the copy in packages/legacy because the name matched. Citations do not make those mistakes impossible. They make them visible before the diff lands.

What a map won’t fix for you

Be clear-eyed about what you’re getting. A grounded map won’t make every edit correct — your agent can still write a bad patch in exactly the right file. If your codebase leans on dynamic dispatch, reflection, or monkey-patching, some symbol lookups will come back thinner than you’d like, because that’s what runtime indirection does to any static index. And if you’re hoping for a percentage — “hallucinated paths down by X%” — you won’t find one here, because nobody can honestly measure that number for your repo but you.

What you can expect is narrower and more useful: the agent stops opening its edits with a guessed path. That first step gets grounded in a real map, and that is where fewer hallucinated edits comes from. Everything after the citation — reading the diff, judging the patch — is still your job, the same as it ever was.

The test costs you almost nothing: index one repo you already know and ask one question you can verify. Start with a path you have been burned by. If the citations are wrong, you’ll see it immediately. If they are right, your agent’s next edit has a better place to land.

// it doesn't know the file. it knows how to find it.

Related reading

More from the Maguyva build log