Repository navigation
Release Windows check fails: FilesystemWorkerClient rejects writes to existing files without expectedIdentity (regression from #3001) #3484
Description
FilesystemWorkerClient.execute() now rejects a plain write to an existing file when the caller doesn't supply expectedIdentity. Callers that go through FilesystemExecutor are fine — it captures the identity at lock acquisition and passes it down. Callers that construct the client directly are not, and scripts/verify-windows-sandbox-e2e.mjs is one of them, so the Release Windows check is currently failing on every PR.
Introduced by #3001 (ec1579bc).
Reproduction
scripts/verify-windows-sandbox-e2e.mjs:95-97:
const insidePath = join(workspace, 'inside.txt');
await writeFile(insidePath, 'seeded');
await execute({ kind: 'write', path: insidePath, content: 'packaged-relay-ok' }); // throwsFilesystemWorkerClientError: The target was created while this call waited for the lock; re-read before writing.
code: 'SANDBOX_FILESYSTEM_OPERATION_FAILED'
domain: 'filesystem'
reason: 'path_changed'
stage: 'validation'
at verifyWindowsSandboxWorkerE2E (scripts/verify-windows-sandbox-e2e.mjs:97:5)
There is no race here. The file is created by the line above, single-threaded and awaited. execute is client.execute({ operation, cwd, mode }) — no expectedIdentity.
Cause
packages/runtime/src/filesystem-worker/client.ts:209-219:
const identity =
input.expectedIdentity && target.targetType !== 'missing'
? input.expectedIdentity
: undefined;
if (!identity && target.targetType !== 'missing' && access === 'write') {
throw clientError('path_changed', 'validation', requestId, '...');
}expectedIdentity is optional (client.ts:67) with no internal fallback — it appears only at lines 67, 194, 210 and 211. So the condition reduces to: any write to an existing target from a caller that didn't supply a T0 identity fails.
The reconciliation logic itself is right, and the comment at client.ts:194 correctly explains why the identity must not be re-derived after the lock is held. What's missing is the third case: a caller that has no T0 identity at all isn't a victim of a swap — it just isn't participating in the CAS. Today that's indistinguishable from "T0 missing, T1 existing".
Scope
- Not user-facing. Tool-driven writes reach the worker through
FilesystemExecutor, which captures identity viacaptureIdentityAtLockAcquisitionbefore the lock wait (filesystem-executor.ts:270for write/edit/format_json,:284for apply_patch) and forwards it. - Direct
FilesystemWorkerClientconsumers are affected. The known one is the Windows sandbox e2e verifier; worth grepping for others before fixing. - Ordinary CI is green, which is why this only surfaced on the Windows release job.
Suggested direction
Distinguish "caller supplied no identity" from "T0 saw nothing". Either make expectedIdentity required at the type level so every direct caller has to decide explicitly, or add an opt-out the verifier can pass to say it isn't participating in the CAS. The first is stricter and would have caught this at compile time.
Whoever picks this up: scripts/verify-windows-sandbox-e2e.mjs reproduces it directly, so the fix is verifiable without a full Windows packaging run.
Filed after this failure blocked #3472's Release Windows check. Reported by an AI-assisted review process; the reproduction and cause were verified against the source at ec1579bc.
Activity
Astro-Han commentedon Aug 22, 2026
Scope update: this blocks the Release Windows check on every open PR, not just one script.
Confirmed failing with the identical error on at least #3454, #3434, #3431 and #3397. Any PR that runs the Windows release job hits it, because they all reach
scripts/verify-windows-sandbox-e2e.mjs. So the Windows release verification path is effectively down until this is fixed — PRs can still merge on ordinary CI, but without that check.The product runtime remains unaffected, as described above: tool-driven writes reach the worker through
FilesystemExecutor, which captures the identity before the lock wait and forwards it. This is a broken verification channel, not a broken product.Raising visibility given the breadth. The fix is still small — distinguish "the caller supplied no identity" from "T0 saw nothing" — and
scripts/verify-windows-sandbox-e2e.mjsreproduces it in three lines without a full Windows packaging run.1625567290 commentedon Aug 22, 2026
I will take this and send a focused fix.
fix(runtime): distinguish unchecked writes from T0-missing races in t…
fix(runtime): distinguish unchecked writes from T0-missing races in t…