Repository navigation
Fix flaky Type check: stop type-check from clobbering the build's tsbuildinfo - #8983
Merged
Merged
Conversation
The shared tsconfig sets `composite: true`, which implies `incremental`. That means `tsc --noEmit` (the `type-check` target) still writes a tsbuildinfo, and because tsconfig.json and tsconfig.build.json share `tsBuildInfoFile: dist/tsconfig.tsbuildinfo`, type-check overwrites the file that `build` (`tsc -b tsconfig.build.json`) owns. `nx run-many --target=type-check` runs `X:type-check` in parallel with `X:build` (type-check only dependsOn ^build). When type-check finishes last, the build's tsbuildinfo now describes a different program (test files included) with every file marked as pending emit. Every downstream `tsc -b` that references `../X` then considers X out of date and re-emits X/dist concurrently, while sibling type-check tasks are reading those .d.ts files. A reader can catch a truncated file mid-write, which surfaces as: error TS2306: File '.../cli-kit/dist/public/node/themes/urls.d.ts' is not a module. Point type-check's tsbuildinfo at node_modules/.cache/tsc/ instead so it never touches the build's incremental state. node_modules is gitignored, so nx does not hash the file as a task input (cache hits are unaffected), and type-check keeps its incremental speed-up locally. After this change, a full `nx run-many --all --target=type-check` leaves cli-kit/dist/tsconfig.tsbuildinfo byte-identical to a standalone clean build (2136 root files, 0 pending emits), whereas before it ended up with 2537 root files including 179 *.test.ts and 537 test outputs emitted into cli-kit/dist by downstream rebuilds.
4 tasks done
isaacroldan
approved these changes
Oct 22, 2026
isaacroldan
enabled auto-merge
October 22, 2026 07:31
karreiro
approved these changes
Oct 22, 2026
karreiro
left a comment
Contributor
There was a problem hiding this comment.
Thank you, @ryancbahan!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WHY are these changes introduced?
The
Type checkCI job is flaky. It failed on #8982 (run) with:…and passed on re-run with no code change. Root cause is a race in how
type-checkandbuildshare TypeScript's incremental state:configurations/tsconfig.jsonsetscomposite: true, which impliesincremental. Sotsc --noEmit(thetype-checktarget) still writes a tsbuildinfo.tsconfig.jsonandtsconfig.build.jsonsharetsBuildInfoFile: dist/tsconfig.tsbuildinfo. SoX:type-checkoverwrites the file thatX:build(tsc -b tsconfig.build.json) owns — with a different program (test files included) and every file flaggedaffectedFilesPendingEmit.nx run-many --target=type-checkrunsX:type-checkin parallel withX:build(type-check onlydependsOn: ^build). On CI, cli-kit's type-check finishes after its build, so the clobbered state wins.tsc -bthatreferences: ../cli-kitthen sees "out of date because buildinfo indicates that some of the changes were not emitted" and re-emitscli-kit/dist/**— concurrently with sibling*:type-checktasks reading those.d.tsfiles. A reader that catches a file between truncate and write sees an empty.d.ts→TS2306: not a module.This is pre-existing and timing-dependent; it isn't caused by the Node bump in #8982, that PR just happened to lose the race.
WHAT is this pull request doing?
One-line change to every
type-checktarget: point its tsbuildinfo atnode_modules/.cache/tsc/type-check.tsbuildinfoso it never touches the build's incremental state.Why this location:
node_modules/is gitignored, so nx doesn't hash it as a task input — type-check cache hits are unaffected (verified: warm run = 21/21 tasks from cache).dist/, so it can't perturb thebundletarget'sdependentTasksOutputFileshash or get wiped bybuildcache restores.Why not simply disable incremental:
--incremental falseerrors with TS6379 (Composite projects may not disable incremental compilation).--composite falsedoes work, but relaxes composite's "every file must be listed ininclude" check for type-check and gives up incremental speed, so the explicit separate file seemed cleaner.e2ehascomposite: falseso the flag is a no-op there; kept for uniformity.Verification (local,
nx run-many --all --target=type-checkfrom a cleandist/+nx reset, inspectingpackages/cli-kit/dist/tsconfig.tsbuildinfoafterwards):fileNames*.test.tsroots*.test.*files incli-kit/distmain)cli-kit:build(reference)After the fix, the post-run state is byte-identical to a standalone build, and
tsc -b --dry --verbosefromthemereports cli-kit "is up to date" — no downstream rebuild, no concurrent writers todist/.† 27
*.test.tsxfiles (81 outputs) are emitted by a plain build today becausetsconfig.build.jsonexcludes**/*.test.tsbut not.tsx. Pre-existing and unrelated; noted as a possible follow-up below.How to manually test your changes?
Possible follow-ups (not in this PR)
referencesat../cli-kit/tsconfig.build.jsonrather than../cli-kit, so downstreamtsc -bevaluates the same program thatcli-kit:buildemits. Today a locally-edited test file can still make a downstreamtsc -brebuild cli-kit with the fulltsconfig.jsonprogram and emit test outputs intodist/.**/*.test.tsxto theexcludeintsconfig.build.jsonfiles so builds stop emitting test outputs.Checklist