Cursor Edit Applied but Build Breaks

Composer says done and touched files lint clean, but npm build fails — classic signature drift, missing import, or stale codegen.

Composer applies, no red squiggles in the touched files, you run pnpm build and it blows up — missing imports, type drift, Prisma client out of date, ESM/CJS mismatch. Cursor’s Apply only checks the local file it touched; it doesn’t run full-graph typecheck, codegen, or know what CI looks like. Net effect: locally green, globally red.

The fix isn’t patching each error one by one; it’s wiring a full build into your Cursor workflow.

Common causes

1. Signature changed; not all call sites updated

Cursor turns foo(a, b) into foo(a, b, c) but only updates the 3 call sites it had open. The other 7 in the repo break with “Expected 3 arguments, but got 2.”

How to judge: pnpm typecheck 2>&1 | grep "Expected" — errors clustered around one function/type.

2. New file missing import or wrong import path

Composer creates src/utils/parseInvoice.ts but callers use from "./utils/parse-invoice" (kebab-case) or from "@/utils/parseInvoice" (depends on path alias). Dev server tolerant; build strict.

How to judge: build error mentions “Cannot find module” or “Module not found.”

3. Codegen didn’t run

After Prisma / GraphQL / protobuf / OpenAPI schema change, the generated client/types weren’t regenerated. The new field referenced in code doesn’t exist in __generated__/.

How to judge: error points to node_modules/.prisma/, src/generated/, __generated__/, etc.

4. ESM / CJS mismatch

Composer wrote import { foo } from "esm-only-package" in a CJS project, or require() in a pure ESM project. Dev (ts-node / tsx) tolerates; build (esbuild / vite / rollup) breaks.

How to judge: error says “ERR_REQUIRE_ESM,” “Cannot use import statement outside a module,” or “is not a function.”

5. References env / files that don’t exist in CI

New code reads process.env.NEW_TOKEN or a local fixture file. Works locally; CI container has neither.

How to judge: build error mentions env name or file path; local builds fine, CI breaks.

6. Multiple tsconfigs (dev vs build)

tsconfig.json is lax (noEmit, skipLibCheck); tsconfig.build.json is strict (strict, noUnusedLocals). Cursor checks against the loose one; build uses the strict one.

How to judge: ls tsconfig*.json — multiple files, compare strict flags.

Before you start

  • Identify whether build fails locally, in CI, or only in production deploy — one-spot failures point at env / config diffs.
  • Commit before reproducing so you don’t lose track of which change broke what.
  • Note Cursor version and active model — import-path style varies (some prefer relative, some prefer path alias).

Info to collect

  • Full build error log (first line + last line; middle is usually cascading).
  • Last Composer turn’s prompt + diff stat.
  • tsconfig.json / tsconfig.build.json and the build script in package.json.
  • Whether a codegen step exists and when it last ran successfully.
  • Local Node / pnpm version vs CI versions.

Shortest fix path

In “full-graph scan → patch by error class” order.

Step 1: Full typecheck + build

pnpm typecheck   # or tsc --noEmit
pnpm build

Read the first error, not the last — AI-introduced errors cascade; the first is closest to root cause.

Step 2: Signature changes — have Composer find call sites

I changed the signature of `foo` from (a, b) to (a, b, c).
List EVERY call site in the repo and update each one.
After updating, run `pnpm typecheck` and paste the result.

Make the agent run typecheck itself.

Step 3: Missing import — fix the path

Build fails with "Cannot find module './utils/parse-invoice'".
The file is actually at src/utils/parseInvoice.ts (camelCase).
Update all import paths to match. Verify with tsc --noEmit.

Step 4: Stale codegen — regenerate

pnpm prisma generate
pnpm codegen           # GraphQL
pnpm proto             # protobuf

Add to .cursorrules:

After any change to *.prisma, *.graphql, or *.proto, you MUST run the matching codegen command before declaring the task done.

Step 5: ESM/CJS — match the project type

Check package.json "type" field. "type": "module" → use import throughout; missing or "type": "commonjs" → use require. Have Composer harmonize, and remember ESM needs explicit .js extensions in imports.

Step 6: CI-only failures — env + tsconfig diff

diff tsconfig.json tsconfig.build.json
cat .github/workflows/*.yml | grep -A 3 env

Hand the strict tsconfig to Composer:

We use tsconfig.build.json (strict mode) for production. Re-check your changes under that config and fix any new errors.

How to verify the fix

  • Local pnpm typecheck && pnpm build both pass.
  • After push, CI is fully green — not just unit tests.
  • On a clean machine, pnpm install && pnpm build works (validates env / lockfile didn’t drift).

If it still fails

  • Reduce to the smallest broken thing: one import or one type error.
  • Roll back the Composer commit, confirm build recovers, reapply changes hunk by hunk.
  • Search forum.cursor.com for the exact error string; include tsconfig + package.json + log.
  • Grab View → Output → Cursor agent logs and post to Bug Reports.

Prevention

  • CI policy: every PR runs full typecheck + build + the whole test suite, not just unit.
  • .cursorrules: “After any code change, run pnpm build and report errors before finishing.”
  • Pre-commit hook: at minimum tsc --noEmit on staged files plus their importers.
  • For schema-driven projects (Prisma / GraphQL / Protobuf), make “schema change → codegen” a rule.
  • End Composer tasks with “I ran the build and it succeeded” — not just “I’m done.”

Tags: #Troubleshooting #Cursor #Debug #Build break