Repository navigation
[Bug]: native Windows: runtime.checkpoint_artifacts capture and materialize always fail because the copied-file durability flush uses a read-only handle #6562
Description
Preflight
- I searched existing issues and discussions for this behavior.
- This report is not an unpatched security vulnerability.
- The report and attachments contain no credentials or private/internal material.
Issue origin
Observed or reproduced in a real environment
LoopX version or commit
main at 81ff72b64 (release 1.4.2), source checkout on native Windows 11 with Node 22 (node --experimental-strip-types). The failing assertion is host-independent of the checkout: any native Windows run of the checkpoint artifact suite reproduces it.
Host or runtime surface
Not host-specific: the shipped control-plane effect runtime.checkpoint_artifacts, reached by loopx research-checkpoint capture, the Codex and research checkpoint hosts, and every materialize caller. The defect is Windows-only.
LoopX area
Control plane (goals, todos, quota, scheduler, registry, runtime)
Problem
On a native Windows host, runtime.checkpoint_artifacts can never capture or materialize a checkpoint unit. copyComponent in loopx/control_plane/runtime/checkpoint_artifacts.ts flushes every freshly copied member through a read-only handle (open(destination, "r") + handle.sync()), and Windows FlushFileBuffers (Node fsync) requires update access to the handle, so each capture aborts with EPERM -4048 fsync and no unit is published. Users on Windows cannot capture a checkpoint at all, and materialize cannot stage the unit it restores.
The read-only reopen is deliberate and recent: #6415 changed this call site from open(destination, "r+") to open(destination, "r") because copyFile preserves a read-only participant's mode (e.g. 0o444) and r+ then fails with EACCES for an ordinary non-root POSIX controller. The durability flush itself is also deliberate: #6258 fixed the identical read-only-handle flush in the backup-state owner (loopx/control_plane/coordination/sqlite_backup.ts), where the same Windows EPERM -4048 had blocked state backups. A correct fix must keep the flush on every platform and satisfy both cases: Windows needs an update handle for FlushFileBuffers, while a POSIX read-only copy denies r+ but can sync through a read-only handle.
Minimal reproduction
On native Windows at 81ff72b64 with Node 22:
node --no-warnings --experimental-sqlite --experimental-strip-types --test tests/control_plane_ts/checkpoint_artifacts.test.ts
8 of 13 tests fail with the error below; the capture/materialize cases and the SQLite snapshot cases all abort in copyComponent. The same failure reproduces through the shipped runtime entry, e.g. effect_runtime_result("runtime.checkpoint_artifacts", {"action": "capture", ...}) with any component.
Expected behavior
Capture publishes the unit, materialize restores it byte-for-byte with the reviewed modes, and the durability flush is retained, on Windows exactly as on POSIX.
Actual behavior
Every capture/materialize aborts with Error: EPERM: operation not permitted, fsync (errno -4048) from copyComponent, so no checkpoint unit can be created or restored on Windows.
Sanitized diagnostics
test at tests\control_plane_ts\checkpoint_artifacts.test.ts:24:1
Error: EPERM: operation not permitted, fsync
at async fsync (node:internal/fs/promises:1654:10)
at async copyComponent (loopx/control_plane/runtime/checkpoint_artifacts.ts:141:10)
at async copyComponent (loopx/control_plane/runtime/checkpoint_artifacts.ts:132:7)
at async checkpointArtifacts (loopx/control_plane/runtime/checkpoint_artifacts.ts:320:30)
errno: -4048, code: 'EPERM', syscall: 'fsync'
Probe results on the same host: open(file, "r") + sync() fails EPERM -4048 even for a writable file; open(file, "r+") + sync() succeeds; for a read-only copy, r+ fails EPERM, and after granting owner write access the update handle sync succeeds with the mode restored afterwards.
Additional context
This is the same defect class as #6258 (merged) and was introduced by #6415 (merged). A PR that keeps the flush, opens the copied member for update, and temporarily grants owner access only to the staged copy when the copy itself is read-only (restoring the reviewed mode before publication) is being prepared.
Activity
coordination: backfill agent-z4k9 claim (issue loopx-project#6562, PR l…