Turbopack persistent dev cache always fails on Windows with "Access is denied (os error 5)" during commit, disabling memory eviction
PerformanceTurbopack
### Link to the code that reproduces this issue
https://github.com/chippleh1392/next-turbopack-fs-cache-windows-repro
### To Reproduce
1. On Windows, install and start the reproduction in development (`npm install`, then `npm run dev`). The app enables the two experimental flags from the 16.3 announcement:
```js
// next.config.js
module.exports = {
experimental: {
turbopackFileSystemCacheForDev: true,
turbopackMemoryEviction: 'full',
},
}
```
2. Load `http://localhost:3000` a few times.
3. Wait about 10 seconds for the background persist to run.
### Current vs. Expected behavior
Current: every dev session fails its first cache commit and permanently disables persistence for that session. stderr shows:
```
Persisting failed: Unable to commit operations
Caused by:
Access is denied. (os error 5)
Persisting is disabled for this session due to an unrecoverable error. Stopping the background persisting process.
```
`.next/dev/cache/turbopack/<version>/` only ever contains `CURRENT`, no SST files. Because `turbopackMemoryEviction` depends on the filesystem cache, eviction never engages, so dev server memory grows unbounded exactly as it did before 16.3. On a small app (~146 source files) I measured the dev process at 1.7 GB RSS within 2 to 3 minutes of route compilation, the same curve as with the cache disabled.
Expected: the cache commit succeeds, cache files accumulate on disk, and memory eviction bounds dev-server RSS as described in the 16.3 Turbopack post.
The failure is deterministic on Windows. I reproduced it on `16.3.0-preview.5`, `16.3.0-canary.77`, and `16.3.0-canary.78`, in multiple directories (including plain `C:\tmp\...`), with a clean `.next` each time, with Windows Defender path and process exclusions applied, and with Controlled Folder Access off. A regular-file `sync_data` in the same directory succeeds.
I believe the root cause is in `turbo-persistence`. `TurboPersistence::commit()` syncs the database directory unconditionally:
```rust
// turbopack/crates/turbo-persistence/src/db.rs (canary)
// Sync the directory to ensure the new directory entries (file name -> inode mappings)
// are durable before we update CURRENT. ...
File::open(&self.path)?.sync_data()?;
```
On Windows, `File::open` on a directory produces a handle opened with `GENERIC_READ | FILE_FLAG_BACKUP_SEMANTICS`, and `sync_data()` calls `FlushFileBuffers`, which requires write access on the handle. `FlushFileBuffers` on a read-only directory handle always fails with `ERROR_ACCESS_DENIED` (5).
Syscall-level check replicating what Rust std does (Python/ctypes):
```
CreateFileW(dir, GENERIC_READ, ..., FILE_FLAG_BACKUP_SEMANTICS) + FlushFileBuffers
-> FAILED, WinError 5 (ACCESS_DENIED)
CreateFileW(dir, GENERIC_READ|GENERIC_WRITE, ..., FILE_FLAG_BACKUP_SEMANTICS) + FlushFileBuffers
-> OK
```
A possible fix is to skip the directory sync on Windows (directory-entry durability does not map to `FlushFileBuffers` semantics there), or to open the directory handle with write access on Windows before flushing.
### Provide environment information
```bash
Operating System:
Platform: win32
Arch: x64
Version: Windows 11 Home
Available memory (MB): 32610
Available CPU cores: 20
Binaries:
Node: 24.13.1
npm: 11.8.0
Yarn: 1.22.22
pnpm: 10.26.0
Relevant Packages:
next: 16.3.0-canary.78
eslint-config-next: N/A
react: 19.2.0
react-dom: 19.2.0
typescript: N/A
Next.js Config:
output: N/A
```
### Which area(s) are affected? (Select all that apply)
Turbopack, Performance
### Which stage(s) are affected? (Select all that apply)
next dev (local)
### Additional context
Local development only, no deployment involved. Filesystem is NTFS; the same failure occurs on paths with no sync software and no third-party antivirus (Defender is the only registered AV, and excluding the paths and `node.exe` changes nothing).
I did not bisect to the canary that introduced the directory sync, but the line is present and unguarded at canary HEAD, and the failure mode means it should reproduce for any Windows user who enables `turbopackFileSystemCacheForDev`. Since 16.3 is expected to enable the filesystem cache and eviction by default, this would surface for all Windows users on upgrade.
0 条评论