Test (shard 1/4) failed on PR objectui#9366's head 87cab756a9 with a whole-suite kill, and it is not a generic flake — it is two named files racing over a scratch directory one of them creates inside the repo root.
Measured, from the primary source
Check-run census taken by me: at 87cab756a9, 36 runs / 32 success / 3 skipped / 1 failure = Test (shard 1/4) (job 103857681521); shards 2–4 success. At the next head 3316efde62, 38 runs / 35 success / 3 skipped / 0 failures, Test (shard 1/4) success (job 103866393737). ⇒ one occurrence, did not recur.
The job log, verbatim:
##[error]Error: Command failed: grep -rFn -I --exclude-dir node_modules --exclude-dir .git
--exclude-dir dist --exclude-dir build --exclude-dir coverage --exclude-dir .next
--exclude-dir .turbo --exclude-dir .changeset --exclude-dir .objectui-tmp
-f /tmp/i18n-dead-keys-EdE7pN/patterns.txt -- /home/runner/work/objectui/objectui
grep: /home/runner/work/objectui/objectui/.vite-oracle-9408-4naMY4: No such file or directory
❯ textFootprint scripts/check-i18n-dead-keys.mjs:670:14
❯ scripts/__tests__/check-i18n-dead-keys.test.ts:475:19
Serialized Error: { status: 2, … }
Cost of the kill: Test Files 1 failed | 777 passed | 1 skipped (779) · Tests 1 failed | 10573 passed | 2 skipped (10576), after a 1,000-second run.
The two ends, both located
The creator — scripts/__tests__/vite-objectstack-spec-dist.test.ts:161:
const dir = fs.mkdtempSync(path.join(repoRoot, '.vite-oracle-9408-'));
⇒ a scratch directory made in the repo root, with a random suffix, created and removed while the suite runs.
The reader — scripts/check-i18n-dead-keys.mjs:660-666 sweeps the whole repo root with grep -rFn -I, excluding only what TEXT_SWEEP_SKIP_DIRS names. ⚠️ .objectui-tmp is in that set; .vite-oracle-* is not.
⇒ when the two run concurrently in the same shard, grep walks into a directory that disappears under it and exits 2.
⛔ The catch is NOT the defect — it is doing exactly what it says
check-i18n-dead-keys.mjs:671-679, quoted rather than characterised:
} catch (error) {
// grep exits 1 when NO line matches at all — a real "nothing found", not a
// failure. Any other exit code (2 = usage/IO error) must not be swallowed.
if (error.status === 1) { … return result; }
… throw error;
}
⭐ It names status 2 and rethrows on purpose. A fix that widens that catch would trade a loud race for a silent one — the sweep would return an under-count and the gate would pass. ⛔ Do not "fix" this by swallowing 2.
⭐ This is the SECOND instance of a class this repo has already fixed once
.changeset/9201-sweep-skip-objectui-tmp.md exists: .objectui-tmp was added to the skip set for exactly this reason. ⇒ the pattern is a test writes scratch state into the repo root, and every repo-root sweeper must then learn its name — a list that has to be maintained by everyone who ever adds a scratch dir.
Two shapes of fix, and this card is not choosing
- Add
.vite-oracle to TEXT_SWEEP_SKIP_DIRS — one line, matches the objectui#9201 precedent, and leaves the class alive for the next scratch dir anyone adds.
- Move the creator to the OS temp dir (
mkdtempSync(join(tmpdir(), …)), which is what check-i18n-dead-keys.mjs:657 itself does for its patterns file) — removes the class rather than the instance, at the cost of whatever made the test want the repo root in the first place. ⚠️ That reason is unmeasured here and must be read before choosing.
⛔ Filed bare on purpose: no domain:*, no priority:*, no type. Triage owns all three.
Generated by Claude Code
Test (shard 1/4)failed on PR objectui#9366's head87cab756a9with a whole-suite kill, and it is not a generic flake — it is two named files racing over a scratch directory one of them creates inside the repo root.Measured, from the primary source
Check-run census taken by me: at
87cab756a9, 36 runs / 32 success / 3 skipped / 1 failure =Test (shard 1/4)(job103857681521); shards 2–4 success. At the next head3316efde62, 38 runs / 35 success / 3 skipped / 0 failures,Test (shard 1/4)success (job103866393737). ⇒ one occurrence, did not recur.The job log, verbatim:
Cost of the kill:
Test Files 1 failed | 777 passed | 1 skipped (779)·Tests 1 failed | 10573 passed | 2 skipped (10576), after a 1,000-second run.The two ends, both located
The creator —
scripts/__tests__/vite-objectstack-spec-dist.test.ts:161:⇒ a scratch directory made in the repo root, with a random suffix, created and removed while the suite runs.
The reader —⚠️
scripts/check-i18n-dead-keys.mjs:660-666sweeps the whole repo root withgrep -rFn -I, excluding only whatTEXT_SWEEP_SKIP_DIRSnames..objectui-tmpis in that set;.vite-oracle-*is not.⇒ when the two run concurrently in the same shard,
grepwalks into a directory that disappears under it and exits 2.⛔ The
catchis NOT the defect — it is doing exactly what it sayscheck-i18n-dead-keys.mjs:671-679, quoted rather than characterised:⭐ It names status 2 and rethrows on purpose. A fix that widens that catch would trade a loud race for a silent one — the sweep would return an under-count and the gate would pass. ⛔ Do not "fix" this by swallowing 2.
⭐ This is the SECOND instance of a class this repo has already fixed once
.changeset/9201-sweep-skip-objectui-tmp.mdexists:.objectui-tmpwas added to the skip set for exactly this reason. ⇒ the pattern is a test writes scratch state into the repo root, and every repo-root sweeper must then learn its name — a list that has to be maintained by everyone who ever adds a scratch dir.Two shapes of fix, and this card is not choosing
.vite-oracletoTEXT_SWEEP_SKIP_DIRS— one line, matches the objectui#9201 precedent, and leaves the class alive for the next scratch dir anyone adds.mkdtempSync(join(tmpdir(), …)), which is whatcheck-i18n-dead-keys.mjs:657itself does for its patterns file) — removes the class rather than the instance, at the cost of whatever made the test want the repo root in the first place.⛔ Filed bare on purpose: no
domain:*, nopriority:*, no type. Triage owns all three.Generated by Claude Code