Cursor Composer Loses Context Mid-Refactor

Composer started strong then forgot which file it was editing — context window blew up; chunk the refactor and recheckpoint.

You start a multi-file refactor in Composer — rename a type, propagate through 15 files, update tests. The first six files look perfect. Around file 9 the diff stops compiling: it is editing the wrong file, reverting an earlier change, or hallucinating an import path that does not exist. The model did not get worse; it ran out of context. Composer’s effective window is finite, and once you pass the limit older edits get evicted, including the very type definition the refactor depends on.

The fix is not “use a bigger model” — it is to chunk the refactor and re-establish ground truth at every chunk boundary.

Common causes

1. Refactor exceeded the effective context window

Even with a 200K-token model, Composer reserves a chunk for tools and system prompt. Effective working room is closer to 80-120K tokens of code. A 20-file TypeScript refactor with full file reads can hit that ceiling fast.

How to judge: count tokens in the files Composer touched. Anything over 60K combined is danger territory.

2. Older edits got evicted by recent tool output

Each tool call’s output (file reads, terminal logs, grep results) sits in context. A few npm run build outputs with stack traces can crowd out the earlier diffs.

How to judge: Composer ran the build or tests several times mid-refactor? That output is now competing with the actual code.

3. Composer was never given a “ground truth” anchor

The first message says “rename UserId to AccountId across the repo” but never pastes the canonical definition. Halfway through, the model forgets the exact shape of the type.

How to judge: scroll up — is there a single message containing the canonical interface AccountId definition?

4. Implicit dependencies between files were never surfaced

UserId is imported by 15 files, but 3 of them re-export it. The model edited the direct imports and missed the re-exports.

How to judge: rg "export.*UserId|export \{.*UserId" --type ts — find re-exports.

5. Mid-refactor file edits by you that the model did not see

You manually fixed a typo in file 5 while Composer was working on file 7. The model still thinks file 5 has the typo; its next edit reverts your fix.

How to judge: did you git status show changes you made that Composer never read?

6. Long agent loops without checkpoints

Agent mode ran 25 tool calls without you committing. By call 20 the model is operating on a context where the first 10 calls were truncated.

How to judge: Composer message has 20+ tool calls in a single response.

Before you start

  • Stop the current Composer run if it is still going — let it finish the current file, then reset.
  • Commit whatever passes lint and type-check so you have a clean rollback point.
  • Note the model in use; Opus 4.7 and Sonnet 4.6 handle long context noticeably differently from older versions.

Information to collect

  • git status and git diff --stat to see how far the refactor got.
  • Compile / type-check errors at the current state.
  • The original Composer message that started the refactor.
  • A list of files Composer was supposed to touch, separated by “done”, “broken”, “untouched”.
  • Whether agent mode or normal Composer was used.

Step-by-step fix

Step 1: Recheckpoint by committing what works

Run type-check / build. Stage and commit every file that passes:

npm run typecheck
git add <files-that-pass>
git commit -m "refactor: rename UserId to AccountId (part 1, files 1-6)"

Discard or stash the half-edited files you do not trust:

git checkout -- src/api/users.ts src/services/auth.ts

You now have a clean base. The refactor is half done but the repo compiles.

Step 2: Re-anchor the refactor with explicit ground truth

Open a fresh Composer chat. First message must pin the canonical definitions:

We are renaming `UserId` to `AccountId` across the repo.

Canonical definition (do not change this shape):

```ts
// src/types/account.ts
export interface AccountId \{
  value: string;
  scope: "internal" | "external";
\}

Files already migrated (do not touch):

  • src/types/account.ts
  • src/api/users.ts
  • src/services/auth.ts

Files still to migrate:

  • src/components/UserCard.tsx
  • src/components/UserList.tsx
  • src/hooks/useUser.ts

For each file: read it, plan the change, apply. Stop after each file. Do not move to the next without my OK.


The pin + done-list + todo-list shape resets the model with a clean working set.

### Step 3: Refactor in chunks of 3-5 files max

Even with a fresh chat, do not paste a list of 20 files. Cap each Composer chat at 3-5 files. Commit between chats. The model has plenty of room when each chunk is small, and a context overflow in one chunk does not poison the others.

### Step 4: Reload files instead of relying on memory

When jumping back to a file Composer touched 10 turns ago:

Before editing src/api/users.ts again, re-read the current contents. Do not rely on what you remember about this file.


This forces a fresh file read and aligns the model with the on-disk state.

### Step 5: Use re-export sweeps for type renames

```bash
# Find re-exports that the direct-rename pass missed
rg "export \{[^}]*UserId[^}]*\}" --type ts
rg "export \* from.*types/user" --type ts

Feed the output to Composer and have it update the re-exports specifically. They are easy to miss when scanning for direct imports.

Step 6: Verify with a clean typecheck after each chunk

npm run typecheck 2>&1 | head -50

If errors stay at zero after each chunk, you are on solid ground. If errors creep up, stop and inspect — do not let Composer fix new errors on top of a stale context.

Verify

  • npm run typecheck and npm run build both pass after the full sequence.
  • rg "UserId" returns zero hits across the repo (or only the intended legacy aliases).
  • The diff applied matches what a manual refactor would produce — no extra unrelated changes snuck in.
  • Run the full test suite and confirm nothing regressed at runtime, not just at the type level.

Long-term prevention

  • Never start a refactor that touches more than 5 files in one Composer chat — split by directory or module.
  • Always pin canonical type / interface definitions in the opening message of a multi-file refactor.
  • Commit between chunks so each chunk has a clean rollback point and the model is not asked to remember work that is already on disk.
  • For agent-mode refactors, set a hard cap of 10 tool calls per response and recheckpoint after each.
  • Keep npm run typecheck --watch running in a side terminal so drift gets caught the moment it appears, not 5 files later.

Common pitfalls

  • “Just continue” prompts after a failed edit — they pile more context onto an already-overflowing chat. Open a new chat instead.
  • Letting Composer run terminal commands repeatedly mid-refactor; each tsc or npm run build output eats 1-5K tokens.
  • Manually editing files while Composer is working — those edits are invisible to the model and get reverted on the next pass.
  • Trusting Composer’s claim “I have updated all 15 files” without running rg to verify.
  • Renaming a symbol that has both type and value forms (TypeScript classes, enums) without telling the model which form lives where.

FAQ

Q: Does using a “long context” model fix this? A: It raises the ceiling but does not change the failure mode. Eventually any refactor wide enough will hit the limit; chunking is the durable fix.

Q: Should I use agent mode or normal Composer for big refactors? A: Normal Composer with explicit per-file approval is safer for refactors. Agent mode wins on isolated tasks; multi-file refactors benefit from human checkpoints.

Q: Can I tell Composer to “remember” something across the chat? A: It will say yes. Do not rely on it. Pin durable facts in your .cursorrules or paste them again at chunk boundaries.

Q: What if the refactor is genuinely sequential (each file depends on the last)? A: Commit after each file and start the next file in a new chat, pasting the relevant pieces of the previous file’s final state. Tedious, but reliable.

Tags: #Cursor #ide #Troubleshooting