Summary
On Windows, every exec call fails with EPERM because writeExecApprovalsRaw in src/infra/exec-approvals.ts uses fs.renameSync(tempPath, targetPath) to atomically replace exec-approvals.json. On Windows, MoveFileExW with MOVEFILE_REPLACE_EXISTING requires DELETE permission on the target file, which fails when any handle (antivirus, search indexer, or transient gateway handle) is open on the target.
Reproduction
- Install OpenClaw on Windows (tested on 2026.5.2, 2026.5.3-1, 2026.5.4, Windows 10.0.26200, Node 24.13.1)
- Start the gateway
- Any exec call produces:
EPERM: operation not permitted, rename 'C:\Users\<user>\.openclaw\.exec-approvals.<PID>.<uuid>.tmp' -> 'C:\Users\<user>\.openclaw\exec-approvals.json'
Root cause
The atomic write pattern (temp + renameSync) added as fix for #54296 is incompatible with Windows. The gateway process holds a transient handle on exec-approvals.json (read during the same exec flow), and renameSync on Windows can't overwrite a file with open handles.
Impact
- ALL exec calls fail — the approval mechanism itself is the gate that fails
gh CLI, shell commands, sub-agents that use exec — all broken
- Only workaround is direct
writeFileSync to the target file (bypassing temp+rename)
- Reproduced across multiple full gateway restarts and OpenClaw updates
Proposed fix
Add a Windows EPERM fallback in writeExecApprovalsRaw:
function writeExecApprovalsRaw(filePath: string, raw: string) {
// ... setup unchanged ...
try {
fs.writeFileSync(tempPath, raw, { mode: 0o600, flag: "wx" });
tempWritten = true;
// Windows: renameSync fails with EPERM when target has open handles
try {
fs.renameSync(tempPath, filePath);
} catch (err) {
if ((err as NodeJS.ErrnoException).code === "EPERM") {
fs.copyFileSync(tempPath, filePath);
fs.unlinkSync(tempPath);
} else {
throw err;
}
}
} finally {
// ... cleanup unchanged ...
}
}
Environment
Summary
On Windows, every exec call fails with EPERM because
writeExecApprovalsRawinsrc/infra/exec-approvals.tsusesfs.renameSync(tempPath, targetPath)to atomically replaceexec-approvals.json. On Windows,MoveFileExWwithMOVEFILE_REPLACE_EXISTINGrequiresDELETEpermission on the target file, which fails when any handle (antivirus, search indexer, or transient gateway handle) is open on the target.Reproduction
Root cause
The atomic write pattern (temp + renameSync) added as fix for #54296 is incompatible with Windows. The gateway process holds a transient handle on
exec-approvals.json(read during the same exec flow), andrenameSyncon Windows can't overwrite a file with open handles.Impact
ghCLI, shell commands, sub-agents that use exec — all brokenwriteFileSyncto the target file (bypassing temp+rename)Proposed fix
Add a Windows EPERM fallback in
writeExecApprovalsRaw:Environment