can1357/oh-my-pi · critical · Error
Failed to replace session file after EPERM (original: ${toEr
Error message
Failed to replace session file after EPERM (original: ${toError(renameError).message}; retry: ${toError(replaceError).message}; rollback: ${rollbackError.message}) What it means
writeTextAtomic replaces the session file via a temp-file rename. When the initial rename fails with EPERM (seen on some platforms when the target is held open, e.g. by antivirus/indexers or another process), the code retries and, on failure, attempts to roll back by renaming a backup over the target. If the rollback also fails, this Error is thrown combining all three messages, leaving the replacement incomplete — the original Error is attached as cause.
Source
Thrown at packages/coding-agent/src/session/session-storage.ts:401
this.renameSync(backupPath, targetPath);
} catch (restoreErr) {
logger.warn("Failed to restore backup after commitGuard rejection", {
sessionFile: targetPath,
backupPath,
error: toError(restoreErr).message,
});
}
this.#discardTemp(tempPath, targetPath);
return;
}
try {
this.renameSync(tempPath, targetPath);
} catch (replaceError) {
try {
this.renameSync(backupPath, targetPath);
} catch (rollbackErr) {
const rollbackError = toError(rollbackErr);
throw new Error(
`Failed to replace session file after EPERM (original: ${toError(renameError).message}; retry: ${
toError(replaceError).message
}; rollback: ${rollbackError.message})`,
{ cause: toError(renameError) },
);
}
throw toError(replaceError);
}
try {
fs.unlinkSync(backupPath);
} catch (err) {
if (!isEnoent(err)) {
logger.warn("Failed to remove session rewrite backup", {
sessionFile: targetPath,
backupPath,
error: toError(err).message,
});
}View on GitHub (pinned to 9690622007)
Solutions
- Close other processes holding the session file (second omp instance, editors, sync clients) and retry the operation.
- Exclude the session directory from antivirus/real-time scanning or pause file-sync software (OneDrive/Dropbox) for ~/.omp.
- Check directory permissions: ensure the user can create/rename/delete files in the session directory.
- Inspect the error's cause and message trio to determine which stage failed; restore from the .bak/backup file if present, or recreate the session from the last valid JSONL.
Example fix
// before: operation fails while Dropbox syncs the session dir await storage.writeTextAtomic(path, text); // after: pause sync client or relocate sessions const dir = path.join(os.homedir(), ".omp", "sessions"); // ensure not inside a synced folder await storage.writeTextAtomic(path, text);
Defensive patterns
Strategy: retry
Validate before calling
import { access, constants } from "node:fs/promises";
await access(sessionDir, constants.W_OK); // throws early if dir not writable
// also ensure no second omp instance holds the file:
// check for a lock/pid file in the session dir before writing Type guard
function isAtomicReplaceFailure(err: unknown): err is Error & { cause: unknown } {
return err instanceof Error &&
err.message.startsWith("Failed to replace session file after EPERM");
} Try / catch
try {
await storage.writeTextAtomic(target, text);
} catch (err) {
if (isAtomicReplaceFailure(err)) {
logger.error("Atomic session replace failed (lock/AV/sync client?)", { cause: err.cause });
// look for leftover backup file to restore, then retry after unlocking
} else throw err;
} Prevention
- Run only one process against a given session file.
- Exclude the session directory from antivirus real-time scanning and file-sync tools (Dropbox/OneDrive).
- Keep the session directory on a local writable filesystem, not a synced/network folder.
- On Windows, prefer storing sessions outside user-synced profile folders.
When it happens
Trigger: renameSync of the temp file fails (typically EPERM/EACCES because the target file is locked by another process, a sync client, or Windows AV), the retry rename also fails, and restoring the backup over the target fails too (e.g. backup already moved or target locked).
Common situations: Windows file locking by antivirus/Defender or Dropbox/OneDrive syncing the session directory; two omp processes running against the same session file; read-only or permission-restricted session directory after a permission change.
Related errors
- could not create temporary file
- GetFinalPathNameByHandleW failed with code {0}
- truncated u16
- truncated NtQueryDirectoryFile record
- Cleanse session could not be persisted
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/6810abd0da67c4ba.
Report an issue: GitHub.