Skip to content

finding(test-infra): a repo-root scratch dir (.vite-oracle-*) vanishes under check-i18n-dead-keys's repo-wide grep, exit 2 kills the whole shard — second instance of the objectui#9201 class #9468

Description

@claude

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 creatorscripts/__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 readerscripts/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

  1. 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.
  2. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions