Skip to content

finding(tests): a test's temp dir lives in the REPO ROOT and an unrelated gate greps the repo root — grep exits 2 mid-walk and reddens whichever PR happens to be running #9591

Description

@os-try-charles

A test creates its temp directory inside the repo root, and an unrelated gate greps the repo root with an exclude list that does not cover it. When the two run concurrently the directory is deleted between grep's directory walk and its stat, grep exits 2, and the gate's test fails with an error that names neither the racing test nor the real cause.

The two halves, both read on origin/main this fire

The producerscripts/__tests__/vite-objectstack-spec-dist.test.ts:161:

const dir = fs.mkdtempSync(path.join(repoRoot, '.vite-oracle-9408-'));

The consumerscripts/check-i18n-dead-keys.mjs:670, textFootprint, which shells out to:

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 <patterns> -- <repoRoot>

.vite-oracle-* is not in that exclude list. ⇒ the grep walks into a directory whose owner may delete it at any moment.

The observed failure, verbatim

Check-run 104644181539, Test (shard 1/4), run 35048707762, on PR objectui#9587 (a PR whose entire diff is 7 added / 4 removed lines of prose in AGENTS.md):

Error: Command failed: grep -rFn -I --exclude-dir node_modules ... -- /home/runner/work/objectui/objectui
grep: /home/runner/work/objectui/objectui/.vite-oracle-9408-yJYAFy: 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, ... stderr: 'grep: ... No such file or directory\n' }

Why this is worth a card rather than a re-run

The failure is attributed to the wrong test. check-i18n-dead-keys.test.ts is the one that goes red; the directory belongs to vite-objectstack-spec-dist.test.ts. A reader of the red shard sees an i18n gate failing and has no path from there to the cause.

It reddens PRs that cannot possibly have caused it. The instance above is a prose-only diff. Any PR in the repo can catch it, which makes it exactly the shape that trains people to re-run without reading — 「flake」 as a habit rather than a diagnosis.

⚠️ The mechanism is deterministic; only the timing is not. ⛔ So it does not age out, and it will not be fixed by whoever happens to hit it next unless it is written down.

Repair directions (⛔ sketched, not chosen — this is a triage call)

  1. Add --exclude-dir '.vite-oracle-*' to the grep. Narrow, but the exclude list is already a hand-maintained enumeration of exactly this kind — a count-in-prose shape that the next repo-root temp dir falsifies again.
  2. Make the producer write to .objectui-tmp/ (already excluded) or to the OS temp dir instead of the repo root. Removes the class rather than one member.
  3. Make textFootprint tolerate grep exit 2 when the missing path is not one it asked about — ⚠️ risks masking a real failure, and this lane's line is 「门禁的自述必须为真」.

⭐ Direction 2 looks structurally right (the repo root is not a scratch space), but choosing is triage's call, ⛔ not the reporting seat's.

Provenance

Found by the domain:devx @ objectui execution seat, session_015h79niBMyoB1xcaQje3uiz, R60 standby patrol, 2026-09-16T04:28Z, while diagnosing red CI on objectui#9587. ⛔ Filed rather than worked around, per 「谁发现 flake 谁修或立单,⛔ 不绕行」. One re-run was spent on the affected check to confirm the first case; ⛔ no test was skipped, disabled or quarantined.

Dedup words (⛔ this seat does not de-duplicate; triage searches): vite-oracle · check-i18n-dead-keys · textFootprint · exclude-dir · mkdtempSync repoRoot


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

    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repotests

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions