can1357/oh-my-pi · error · Error
could not relocate the session back to ${snapshot.sessionDir
Error message
could not relocate the session back to ${snapshot.sessionDir} (${error instanceof Error ? error.message : String(error)}); the session file remains at ${movedFile} What it means
rollbackMove() attempts to relocate a session back to its original directory captured in a state snapshot. If that move fails, the original moveTo error is wrapped in this message that reports both the intended destination and where the session file currently sits, so the caller knows the session was NOT restored and data is at movedFile. The wrapper prevents losing the underlying cause while leaving state unrestored.
Source
Thrown at packages/coding-agent/src/session/session-manager.ts:1376
/**
* Undo a {@link moveTo} using a {@link captureState} snapshot: rename the
* session and artifacts back into the captured bucket, then restore the
* captured metadata (cwd, header, additionalDirectories). The captured
* header is persisted after relocation so a fresh open of the source
* session sees the pre-move metadata, including workspace roots the move
* filtered out. Rollbacks must not re-enter forward-move hooks, so this
* bypasses AgentSession entirely. If the rename-back itself fails, the
* manager stays pointed at the actual moved file (restoring the snapshot
* would split the transcript across a recreated source and the stranded
* target) and the error names where the session file actually lives.
*/
async rollbackMove(snapshot: SessionManagerStateSnapshot): Promise<void> {
try {
const targetSessionDir = snapshot.sessionFile ? path.dirname(snapshot.sessionFile) : snapshot.sessionDir;
await this.moveTo(snapshot.cwd, targetSessionDir);
} catch (error) {
const movedFile = this.getSessionFile();
throw new Error(
`could not relocate the session back to ${snapshot.sessionDir} (${error instanceof Error ? error.message : String(error)}); the session file remains at ${movedFile}`,
);
}
this.restoreState(snapshot);
// The inverse moveTo already rewrote the source file with the
// target-filtered header. Persist the captured one so disk and memory
// agree after a fresh open.
if (this.#persist && this.#sessionFile) {
this.#forceFileCreation = true;
this.#rewriteRequired = true;
await this.#rewriteAtomically();
}
}
/** Switch to a different session file (resume / branch). */
async setSessionFile(sessionFile: string): Promise<void> {
await this.#setSessionFile(sessionFile);
}
View on GitHub (pinned to 9690622007)
Solutions
- Recreate the original session directory (snapshot.sessionDir) with write permissions, then call rollbackMove again.
- Manually move the file from getSessionFile()/movedFile back to the target directory.
- If the original directory is intentionally gone, adopt the current location instead of rolling back.
- Read the inner parenthesized error for the precise filesystem cause (ENOENT, EACCES, EBUSY).
Example fix
// before
await mgr.rollbackMove(snapshot); // ENOENT if dir deleted
// after
if (!existsSync(snapshot.sessionDir)) {
mkdirSync(snapshot.sessionDir, { recursive: true });
}
await mgr.rollbackMove(snapshot); Defensive patterns
Strategy: try-catch
Validate before calling
if (!existsSync(snapshot.sessionDir)) {
mkdirSync(snapshot.sessionDir, { recursive: true });
} Type guard
null
Try / catch
try {
await mgr.rollbackMove(snapshot);
} catch (err) {
// session file is still at the path in err.message; move it manually
logger.error("Rollback failed; session left in place", { err });
} Prevention
- Ensure the original directory exists and is writable before moving a session away.
- Avoid moving sessions onto different filesystems (rename may fail with EXDEV).
- Don't delete/rename the source project directory while a session move is in flight.
When it happens
Trigger: Calling SessionManager.rollbackMove(snapshot) when moveTo(snapshot.cwd, targetSessionDir) throws — e.g. the original directory no longer exists, permissions changed, the target path is not writable, or snapshot.sessionFile points into a removed directory.
Common situations: Undoing a session move after the original project directory was deleted or renamed; read-only filesystem; cross-device rename restrictions; concurrent process holding a lock on the destination.
Related errors
- Failed to move artifacts and rollback: ${rollbackErr instanc
- Failed to move session file and rollback: ${rollbackErr inst
- Cleanse session could not be persisted
- Session file not found: ${resolved}
- No artifacts directory found: {artifacts_dir}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/8fe4f62390c628c6.
Report an issue: GitHub.