#281·feynman

rmSync races antivirus handle on freshly written esbuild.exe — intermittent EPERM in npm test/prepack on Windows

Author: francescovidaich964Created Sep 10, 2026Updated Sep 10, 2026

Description

Intermittent EPERM during npm test / prepack on Windows when the esbuild package tree is being replaced.

Environment

  • OS: Windows 11 Pro (build 26200), x64, non-elevated
  • Node: 24.x
  • Antivirus: Microsoft Defender (default)

Steps to reproduce

  1. Run npm test or prepack (esbuild package patch path).
  2. Observe intermittent EPERM on the freshly written esbuild.exe.

Actual behavior

rmSync throws EPERM; the failure is transient — no process holds the file, and the identical rmSync succeeds moments later.

Root cause

scripts/lib/pi-esbuild-package-patch.mjs:485 calls rmSync(dir, { recursive: true }) with no force and no retries, racing Defender's handle on a freshly written 11.6 MB esbuild.exe.

The repo already solved this: scripts/lib/temporary-tree-cleanup.mjs exports removeTemporaryTree, which retries with exponential backoff and lists EPERM in RETRYABLE_REMOVE_CODES. It is used in only 2 scripts; across scripts/ there are 56 rmSync calls and zero use retries.

Expected behavior

The tree removal retries with backoff instead of failing the build.

Proposed fix (PR attached)

Use removeTemporaryTree at the call site (adds force: true plus bounded retries).

Test note

No new call-site test is added: the helper is already tested in tests/temporary-tree-cleanup.test.ts (which injects a failing remove to simulate EPERM), and asserting retry behavior at this call site would require widening patchPiEsbuildPackageTree's API purely for testability. Happy to add that plumbing if you'd prefer call-site coverage.

Related

  • Bare tar in scripts/lib/deterministic-archive.mjs breaks under Git Bash's GNU tar, which reads -f C:\... as remote host C: (System32 bsdtar is fine; the fix is not a one-liner because GNU tar needs --force-local, which bsdtar rejects).
  • The documented irm … | iex install command trips a Defender ClickFix signature.

Impact

Intermittent build/test failures on Windows; no data loss (transient race only).