can1357/oh-my-pi · error · Error
Failed to persist ${sourceName} session
Error message
Failed to persist ${sourceName} session What it means
SelectorController throws this when a foreign-source session (e.g. an imported/collab or external provider session) was selected and imported in memory, but persistForeignSession did not yield a session file on disk. The controller cannot resume a session without a backing file, so it aborts the import-and-resume flow. It signals an internal persistence failure, not a user-selection problem.
Source
Thrown at packages/coding-agent/src/modes/controllers/selector-controller.ts:1606
const foreignByPath = new Map(foreignSessions.map(session => [session.path, session]));
sessions = foreignSessions.map(foreignSessionInfoToSessionInfo);
onSelectSession = async session => {
try {
await this.ctx.settings.flush();
} catch (error) {
this.ctx.showError(
`Failed to save pending settings: ${error instanceof Error ? error.message : String(error)}`,
);
return false;
}
const foreignSession = foreignByPath.get(session.path);
if (!foreignSession) throw new Error(`Selected ${sourceName} session is no longer available`);
const imported = await persistForeignSession(store, foreignSession, {
fallbackCwd: this.ctx.sessionManager.getCwd(),
suppressBreadcrumb: true,
});
const sessionFile = imported.getSessionFile();
if (!sessionFile) throw new Error(`Failed to persist ${sourceName} session`);
await imported.close();
return await this.handleResumeSession(sessionFile, { settingsFlushed: true });
};
selectorOptions = {
title: `Import ${sourceName} Session`,
scopeLabel: false,
showCwd: true,
};
} else {
const [loadedSessions, pinnedIds] = await Promise.all([
SessionManager.list(this.ctx.sessionManager.getCwd(), this.ctx.sessionManager.getSessionDir()),
loadPinnedSessionIds(),
]);
sessions = loadedSessions;
const historyStorage = this.ctx.historyStorage;
const historyMatcher = historyStorage
? (query: string) => historyStorage.matchingSessionIds(query)
: undefined;View on GitHub (pinned to 9690622007)
Solutions
- Verify the session storage directory (sessionManager cwd / OMP data dir) is writable and has free space
- Check persistForeignSession's store configuration — ensure a FileSessionStorage-backed store is used so a session file is created
- Retry the import; if persistent, inspect logs for the underlying persistence error from persistForeignSession
- Report the underlying persist failure — getSessionFile() being empty after a successful import is a bug in the import path
Example fix
// before
const imported = await persistForeignSession(store, foreignSession, { fallbackCwd });
const sessionFile = imported.getSessionFile();
// after
const imported = await persistForeignSession(store, foreignSession, { fallbackCwd });
const sessionFile = imported.getSessionFile();
if (!sessionFile) {
// ensure the store has a writable directory before persisting
await fs.mkdir(sessionDir, { recursive: true });
throw new Error(`Failed to persist ${sourceName} session`);
} Defensive patterns
Strategy: try-catch
Validate before calling
const store = new FileSessionStorage({ dir: sessionDir });
await fs.access(sessionDir, fs.constants.W_OK); // storage dir must be writable Type guard
function hasSessionFile(s: { getSessionFile(): string | undefined }): s is { getSessionFile(): string } {
return typeof s.getSessionFile() === "string" && s.getSessionFile().length > 0;
} Try / catch
try {
const session = await selector.importAndResume(foreignSession);
} catch (err) {
if (err.message.startsWith("Failed to persist")) {
ui.showError("Could not write the imported session to disk. Check disk space/permissions and retry.");
} else throw err;
} Prevention
- Ensure the session storage directory exists and is writable before importing
- Monitor disk space where session files are written
- Prefer FileSessionStorage-backed stores so imports always produce a file
- Log persistForeignSession failures instead of swallowing them
When it happens
Trigger: Calling the selector's import flow (via handleSelect in SelectorController) when the imported session's getSessionFile() returns undefined — i.e. persistForeignSession completed but did not write/attach a session file path.
Common situations: Disk write failures or a session store misconfigured so the imported session has no file path; importing a foreign session whose serialization produced no file; running with a session manager pointed at an unwritable directory.
Related errors
- Cleanse session could not be persisted
- Vibe mode exit cannot persist worker tombstones without the
- Vibe session "${record.id}" changed parent scope before term
- Vibe mode exit requires atomic parent-session persistence.
- Vibe parent session changed before the worker could start.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/a189f2f1f946082d.
Report an issue: GitHub.