Before submitting
Area
apps/server
Steps to reproduce
- Open a project whose working tree has a very large number of untracked files (e.g. a generated directory not covered by
.gitignore, with tens of thousands of files).
- Open the review diff for that project so the server calls
review.getDiffPreview. The untracked fallback is used when the unified working-tree diff fails, and large repos are the likeliest to hit it.
- Watch the process table.
Expected behavior
The untracked part of the review diff is bounded: a capped number of files are diffed, and the result is marked truncated beyond that, as the tracked diff already is.
Actual behavior
readUntrackedReviewDiffs spawns one git diff --no-index process per untracked file, with no cap on the file count (apps/server/src/vcs/GitVcsDriverCore.ts:2177-2224 on main, the Effect.forEach(untrackedPaths, …, { concurrency: 4 }) at :2192).
The only bound is WORKSPACE_FILES_MAX_OUTPUT_BYTES = 120_000 (:55) on the NUL-separated path list from git ls-files --others. At 2 bytes minimum per path, that still allows ~60,000 paths, so up to ~60,000 git processes from one request. Concurrency 4 makes it a long stall, not a spike. Those calls also hold permits on the shared git process semaphore, which delays every other git operation in the meantime. Combined output is not bounded either: each file is capped individually, but the joined result is not.
Impact
Major degradation or frequent failure
Version or commit
main @ c0995d2
Environment
Linux; found by code reading and reproduced in a fork (T3o).
Logs or stack traces
No response
Workaround
Add the untracked directory to .gitignore.
A reference fix from our fork: e35c6ac. It diffs at most 200 untracked files, stops once combined output reaches the tracked-diff cap, and marks the result truncated, with a test in GitVcsDriverCore.test.ts.
Before submitting
Area
apps/server
Steps to reproduce
.gitignore, with tens of thousands of files).review.getDiffPreview. The untracked fallback is used when the unified working-tree diff fails, and large repos are the likeliest to hit it.Expected behavior
The untracked part of the review diff is bounded: a capped number of files are diffed, and the result is marked truncated beyond that, as the tracked diff already is.
Actual behavior
readUntrackedReviewDiffsspawns onegit diff --no-indexprocess per untracked file, with no cap on the file count (apps/server/src/vcs/GitVcsDriverCore.ts:2177-2224onmain, theEffect.forEach(untrackedPaths, …, { concurrency: 4 })at:2192).The only bound is
WORKSPACE_FILES_MAX_OUTPUT_BYTES = 120_000(:55) on the NUL-separated path list fromgit ls-files --others. At 2 bytes minimum per path, that still allows ~60,000 paths, so up to ~60,000gitprocesses from one request. Concurrency 4 makes it a long stall, not a spike. Those calls also hold permits on the shared git process semaphore, which delays every other git operation in the meantime. Combined output is not bounded either: each file is capped individually, but the joined result is not.Impact
Major degradation or frequent failure
Version or commit
main @ c0995d2
Environment
Linux; found by code reading and reproduced in a fork (T3o).
Logs or stack traces
No response
Workaround
Add the untracked directory to
.gitignore.A reference fix from our fork:
e35c6ac. It diffs at most 200 untracked files, stops once combined output reaches the tracked-diff cap, and marks the result truncated, with a test inGitVcsDriverCore.test.ts.