# fix\(server\): tolerate the missing directory fsync on Windows · PR \#9569 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/9569)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: windows-tests/directory-fsync

Target branch: windows-tests/desktop-paths

Head commit: 4c642ebd4f8cd9ef61e2fc03210ea536506be7ac

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/9569)

[Commits](https://git.cafe/pingdotgg/t3code/pull/9569/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/9569/diffs?format=markdown)

## Description

---

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](https://github.com/pingdotgg/t3code/pull/9564); the manual Windows lane comes from [#9538](https://github.com/pingdotgg/t3code/pull/9538).

Model: Claude Fable 5 in Claude Code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!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.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 4c642ebd4f8cd9ef61e2fc03210ea536506be7ac. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Tolerate missing directory fsync on Windows in `bootService` file writer
> The durable file-writing path in [bootService.ts](https://github.com/pingdotgg/t3code/pull/9569/files#diff-9ec1426b86c5c9f63a503a0c78a87a5165a6460ca539deb5c365bda9ff0576f0) 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's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 4c642eb.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->

