Yeachan-Heo/oh-my-codex · warning · AggregateError
detached post-launch lifecycle cleanup failed
Error message
detached post-launch lifecycle cleanup failed
What it means
runDetachedSessionPostLaunch aggregates cleanup steps (native hook events, codex home cleanup, release marker removal); any strict-mode failures are collected and rethrown as an AggregateError with this message.
Source
Thrown at src/cli/index.ts:7442
await strict(async () => {
const { notifyLifecycle } = await import("../notifications/index.js");
await notifyLifecycle("session-end", {
sessionId, projectPath: cwd, projectName: basename(cwd), reason: "session_exit",
});
});
await strict(async () => {
const { markOwnedTeamsLeaderSessionStopped } = await import("../team/state.js");
await markOwnedTeamsLeaderSessionStopped(cwd, sessionId);
});
await strict(() => emitNativeHookEvent(cwd, "session-end", {
session_id: sessionId,
context: buildNativeHookBaseContext(cwd, sessionId, "finished", {
project_path: cwd, project_name: basename(cwd), reason: "session_exit", status: "finished",
}),
}));
await strict(() => cleanupRuntimeCodexHome(runtimeCodexHomeForCleanup, projectLocalCodexHomeForCleanup));
if (releaseMarkerPath) await strict(() => rm(releaseMarkerPath, { force: true }));
if (failures.length > 0) throw new AggregateError(failures, "detached post-launch lifecycle cleanup failed");
}
async function emitNativeHookEvent(
cwd: string,
event: "session-start" | "session-end" | "session-idle" | "turn-complete",
opts: {
session_id?: string;
thread_id?: string;
turn_id?: string;
mode?: string;
context?: Record<string, unknown>;
} = {},
): Promise<void> {
const payload = buildHookEvent(event, {
source: "native",
context: opts.context || {},
session_id: opts.session_id,
thread_id: opts.thread_id,View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Inspect errors of the AggregateError (err.errors) to see which cleanup step failed
- Fix the filesystem issue (permissions, locks) and re-run the cleanup command
- Delete the leftover runtime codex home / release marker manually if it is safe
Defensive patterns
Strategy: fallback
Try / catch
try { await runDetachedSessionPostLaunch(...); } catch (e) {
if (e instanceof AggregateError) for (const inner of e.errors) log.warn('cleanup partial failure:', inner.message);
} Prevention
- Exclude run dirs from antivirus/sync lockers
- Keep consistent ownership of session files
- Run cleanup with the same user that launched
When it happens
Trigger: One or more awaited strict() cleanup helpers reject — e.g. rm of the release marker fails with EPERM/EBUSY, or cleanupRuntimeCodexHome hits a filesystem error.
Common situations: Antivirus/lockers holding files on Windows, NFS stale handles, or permissions changed after the session ran (e.g. files created as root).
Related errors
- preLaunch setup finalization failed
- preLaunch ${completion.operation} failed
- detached Hermes leader has no tmux pane identity
- bound setup finalization denied: ${finalization.cleanup.comp
- detached leader interrupted before release: ${interrupted}
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/6553105e6d21ccd0.
Report an issue: GitHub.