fix(server): tolerate the missing directory fsync on Windows#9569

merged1
windows-tests/desktop-paths
windows-tests/directory-fsync
openedSep 4, 2026byJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 3d ago

writeServiceState and the boot-service installer fsync the parent directory after an atomic rename so the entry survives power loss. Windows lets you open a directory handle but sync on it fails with EPERM, which turned every service-state write into a hard error there; NTFS journals the rename on its own, so ignore that one errno.

Part of the Windows test-suite stack rooted at #9564; the manual Windows lane comes from #9538.

Model: Claude Fable 5 in Claude Code.

๐Ÿค– Generated with Claude Code


Note

Low Risk Narrow platform-specific errno handling around fsync; Unix behavior is unchanged except opening temp files as read-write for sync.

Overview Fixes durable writes on Windows for boot-service install files and service-launcher state/backup paths that atomically rename temp files then fsync the parent directory.

Temp-file flushes now open handles with r+ instead of read-only, because Windows refuses to sync without write access. Directory fsync still runs on Unix for crash safety, but EPERM is ignored on Windows where directory sync is unsupported and NTFS is expected to journal the rename.

In serviceLauncher.ts, directory sync is centralized in syncDirectory (with the same EPERM rule) and writeServiceState calls that helper instead of inlining directory sync.

Reviewed by Cursor Bugbot for commit 4c642ebd4f8cd9ef61e2fc03210ea536506be7ac. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Tolerate missing directory fsync on Windows in bootService file writer

The durable file-writing path in bootService.ts previously failed on Windows because the platform does not support directory fsync. The temp-file flush handle is now opened in read-write mode, and directory sync errors are ignored only when they return EPERM, while other errors still propagate. This lets the write complete on Windows without weakening error handling elsewhere.

Macroscope summarized 4c642eb.

Synced from GitHub

Thread transfer impact

โœ… Thread transfer remains within every enforced ceiling.

โ„น๏ธ No successful main baseline artifact is available yet. This run establishes the initial measurement.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wireโ€”13.4 KiBโ€”15.1 KiBโœ…
CodexThread snapshot wireโ€”7.0 KiBโ€”7.3 KiBโœ…
CodexLive turn WebSocket wireโ€”6.4 KiBโ€”7.8 KiBโœ…
CodexLive turn WebSocket decodedโ€”56.2 KiBโ€”66.4 KiBโœ…
CodexLive turn messagesโ€”8โ€”21โœ…
ClaudeTotal thread wireโ€”13.4 KiBโ€”15.1 KiBโœ…
ClaudeThread snapshot wireโ€”7.0 KiBโ€”7.3 KiBโœ…
ClaudeLive turn WebSocket wireโ€”6.4 KiBโ€”7.8 KiBโœ…
ClaudeLive turn WebSocket decodedโ€”57.0 KiBโ€”66.4 KiBโœ…
ClaudeLive turn messagesโ€”8โ€”21โœ…

Baseline: unavailable ยท PR result: 4c642eb ยท Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 113.8 KiB
  • Claude decoded thread snapshot: 114.5 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

Synced from GitHub

Approvability

Verdict: Approved at 95a55d3

Macroscope's review found this PR approvable โ€” This is a small, platform-specific fix that allows existing Windows service-state, installation, and database durability workflows to complete when directory fsync returns EPERM. File syncing remains explicit, and unrelated filesystem errors continue to propagate.

No code changes detected at 4c642eb. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

Added 1 commit

  • fix(server): make durable writes survive Windows fsync rules4c642eb