AI Hallucinated a File That Doesn't Exist

Agent imports `src/utils/superhelper.ts` that was never created — common, fixable.

Build fails with Cannot find module './utils/superhelper'. You grep the whole project — the file doesn’t exist. Claude Code or Cursor invented an import to a utility it “expected to be there.” This is one of the most common LLM failure modes: based on training data and similar-project naming conventions, the model “completes” a plausible-looking path without ever creating the actual file. The good news: easy to fix. The compiler tells you exactly which line, and there are only two valid fixes — implement it or replace it. This article covers the causes, fix templates, and prevention rules.

Common causes

Ordered by hit rate, highest first.

1. Agent confused its plan with its code

In reasoning it said “I’ll use a formatDate utility.” In code it just wrote import { formatDate } from './utils/formatDate' — it treated the name from its plan as already-implemented code.

// agent wrote
import { formatDate } from '@/utils/formatDate';
// but the project actually uses
import dayjs from 'dayjs';

How to spot it: Inspect the reasoning trace. Did it ever say “create” or “implement”? If there’s an import but no creation action, this is it.

2. Defaulted to a utility it “expects” to exist

LLMs have seen src/utils/cn.ts, src/lib/utils.ts, src/helpers/format.ts in so many codebases that they assume yours has them too. TypeScript templates and Next.js / shadcn ship lib/utils.ts by default — but maybe you didn’t use shadcn.

How to spot it: Search for stock template paths like src/lib/utils, src/utils/cn, @/lib/db. If you never created them, that’s the bug.

3. Package name from training data

Wrote import { useDebounce } from 'react-use' but you installed usehooks-ts, not react-use. Error: Cannot find module 'react-use'. Technically package hallucination, not file hallucination, but the root cause is identical.

How to spot it: Check package.json; npm list <package> returns nothing — package hallucination.

4. Agent took the wrong workspace path in a monorepo

packages/ui/src/Button.tsx exists, but agent (working in packages/app) wrote import { Button } from '../ui/Button' — math is wrong. The file exists but the relative path doesn’t resolve.

How to spot it: Path in the error is relative and looks suspicious (../../../ui/); check tsconfig paths and actual directory depth.

5. Casing mismatch (works on macOS, fails in CI)

import './Button' but the file is button.tsx. macOS resolves it; Linux build fails. Not strictly hallucination but the symptom is identical.

How to spot it: git ls-files | grep -i button shows the actual on-disk casing.

6. Agent imported a file it planned to create but forgot

In the plan: “I’ll create src/api/posts.ts.” In the code: only the import, never the creation — context window cut off mid-plan or a step got skipped.

How to spot it: Grep the agent’s Write tool calls for this run; if the missing file isn’t in the list, it was never written.

Shortest path to fix

Ordered by ROI. Most cases fix in under 5 minutes.

Step 1: List every hallucinated import with tsc --noEmit

npx tsc --noEmit 2>&1 | grep -E "TS2307|TS2305|Cannot find"

You’ll see something like:

src/components/Form.tsx:5:23 - error TS2307: Cannot find module '@/utils/superhelper'
src/pages/posts.tsx:8:30 - error TS2307: Cannot find module '@/lib/db'
src/hooks/useAuth.ts:3:15 - error TS2305: Module '@/utils' has no exported member 'verifyToken'

One row, one fix.

Step 2: Decide whether the utility should exist

Open the failing file, look at how the import is used:

import { superhelper } from '@/utils/superhelper';

// ...
const result = superhelper(data, { format: 'json' });

Ask yourself two questions:

  1. Does the project already have an equivalent? (e.g. lodash, dayjs, a helper you wrote earlier)
  2. If not, is it worth a new file?
SituationFix
Equivalent already existsChange the import, don’t create a file
Tiny feature (< 20 lines)Inline at the call site
Genuinely reusable utilityActually create it
Package hallucinationnpm install the real package, or swap to an installed equivalent

Step 3: Grep to find an existing equivalent

Verify before creating:

# By function name
grep -rn "formatDate\|format_date\|dateFormat" src/

# By signature
grep -rn "export function.*Date.*string" src/

# Look for related installed packages
grep -E "(date|format|debounce|throttle)" package.json

If something’s there, swap the hallucinated import for it.

Step 4: Hand the list back to the agent with a precise prompt

Don’t fix every import by hand — feed the list back:

Build is broken. These imports reference non-existent files:

[paste tsc --noEmit output]

Fix rules (strict):
1. Do not create new files unless there is truly no equivalent
2. Before fixing each import, grep the project to check for an existing implementation
3. If a missing npm package, tell me the name — I decide whether to install or swap
4. After fixing, `tsc --noEmit` must be fully green
5. Do not change tsconfig paths

Step 5: For genuinely new files, require a proposal first

If a utility really needs to be created:

You want to create src/utils/X.ts. First output:
1. Full file content (with types)
2. Every call site that will use it
3. Why not use existing lodash / dayjs / native APIs

Wait for my approval before creating it.

This forces a human review and prevents the agent from sprinkling one-call-site “helpers” everywhere.

Prevention

  • In CLAUDE.md / AGENTS.md / .cursorrules write: “Before importing, you must grep or find to confirm the target exists. Never invent a path”
  • Add tsc --noEmit to the agent’s “done” criterion — declaring done requires a clean type check
  • Pre-commit hook runs tsc --noEmit; TS2307 / TS2305 blocks the commit
  • Drop a docs/utils.md at the project root listing common helpers and their real paths — feed it to the agent as context
  • Verify the agent has file-search tools available and uses them — many agents don’t search the file tree proactively by default
  • Keep npm install in its own commit so you can see exactly what was added in any week
  • In monorepos, use tsconfig paths aliases instead of relative paths — hallucination rate drops noticeably

Tags: #AI coding #Debug #Troubleshooting