Skip to content

--incremental: diagnostics caused by a JSON module are never cleared after the JSON file is fixed (7.0.2) #64025

Description

🔎 Search Terms

incremental json stale diagnostics, resolveJsonModule incremental, tsbuildinfo stale error json, semanticDiagnosticsPerFile json, incremental diagnostics not cleared

🕗 Version & Regression Information

  • Broken in: typescript@7.0.2 (tsc -p . with "incremental": true)
  • Still broken in nightly: typescript@7.1.0-dev.20260825.1 (identical repro output)
  • Works in: typescript@5.9.3 — the identical file cycle clears the error correctly
  • Not expressible in the Playground (requires --incremental state across multiple compilations)

💻 Code

Three files:

tsconfig.json

{
  "compilerOptions": {
    "strict": true,
    "noEmit": true,
    "incremental": true,
    "resolveJsonModule": true,
    "esModuleInterop": true
  }
}

data.json

{ "title": "hello" }

check.ts

import type data from "./data.json";

type Shape = { title: string };
type Covers<T extends Shape> = T;

export type Check = Covers<typeof data>;

Repro steps:

rm -f tsconfig.tsbuildinfo
printf '{ "title": "hello" }\n' > data.json
tsc -p .    # 1. cold run: clean ✅

printf '{ }\n' > data.json
tsc -p .    # 2. warm run: TS2741 — correct ✅

printf '{ "title": "fixed" }\n' > data.json
tsc -p .    # 3. warm run: STILL TS2741 ❌ — data.json on disk has "title"

rm -f tsconfig.tsbuildinfo
tsc -p .    # 4. identical files, cache deleted: clean ✅

🙁 Actual behavior

Step 3 keeps failing on every subsequent run:

check.ts(6,28): error TS2741: Property 'title' is missing in type '{}' but required in type 'Shape'.

The diagnostic describes content that no longer exists ('{}' — the file contains "title": "fixed"). No edit to the JSON file ever clears it — neither new valid content nor restoring the original bytes. Only deleting tsconfig.tsbuildinfo (or turning off incremental) recovers. Note the asymmetry: the JSON change that introduces the error (step 2) is detected on a warm run; only clearing is broken.

Diffing tsconfig.tsbuildinfo between steps 2 and 3 shows the mechanism: the only change is data.json's content-hash version in fileInfos — so the changed JSON was registered — but the semanticDiagnosticsPerFile entry for check.ts still holds the old TS2741 ("messageArgs": ["title", "{}", "Shape"]) and is replayed instead of the file being re-checked.

The same behavior reproduces with a value import (import data from "./data.json"), with "moduleResolution": "bundler", and in a large real project (Next.js app where locale JSON catalogs are type-checked against en.json — fixing the catalog after a failing check strands the build red until the buildinfo is deleted).

🙂 Expected behavior

Step 3 exits clean, as typescript@5.9.3 does for the identical sequence: fixing the JSON module re-checks its dependents and clears the cached diagnostics.

Additional information

Related but distinct: microsoft/typescript-go#2666 covers missing invalidation for changed external dependencies; this report is in-project JSON modules, where the changed file's hash is visibly updated in the buildinfo yet dependents' cached diagnostics are not invalidated.


Disclosure: this issue was investigated and written by Claude (Anthropic's AI assistant), working in Claude Code on behalf of the reporter. The repro and the 5.9.3/7.0.2 comparison were executed and verified, not inferred.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions