openclaw/openclaw · error · CatalogParamsError
Codex session is not a non-archived interactive Codex sessio
Error message
Codex session is not a non-archived interactive Codex session
What it means
Thrown by requireCatalogEligibleThread when neither the cached (cadence-safe) page scan nor the forced-refresh scan located the requested thread id among non-archived interactive Codex sessions. Mutating actions (continue/archive/terminal) require an authoritative eligibility confirmation before proceeding.
Source
Thrown at extensions/codex/src/session-catalog-terminal.ts:91
? { canOpenTerminalCodex: true }
: {};
}
export async function requireCatalogEligibleThread(
control: CodexSessionCatalogControl,
threadId: string,
): Promise<CodexSessionCatalogSession> {
// Mutating actions use a fresh pinned control and authoritative thread/read. Passive positive hits
// may use the cadence-safe page memo; only a miss must bypass it before rejecting a new thread.
const cached = await findCatalogEligibleThread(control, threadId, false);
if (cached) {
return cached;
}
const refreshed = await findCatalogEligibleThread(control, threadId, true);
if (refreshed) {
return refreshed;
}
throw new CatalogParamsError("Codex session is not a non-archived interactive Codex session");
}
async function findCatalogEligibleThread(
control: CodexSessionCatalogControl,
threadId: string,
forceRefresh: boolean,
): Promise<CodexSessionCatalogSession | undefined> {
let cursor: string | undefined;
const seenCursors = new Set<string>();
for (let pageIndex = 0; pageIndex < MAX_ACTION_CATALOG_PAGES; pageIndex += 1) {
const page = await control.listPage({
limit: CODEX_SESSION_CATALOG_MAX_PAGE_LIMIT,
...(cursor ? { cursor } : {}),
...(forceRefresh ? { forceRefresh: true } : {}),
});
const candidate = page.sessions.find((session) => session.threadId === threadId);
if (candidate) {
if (isInteractiveThreadSource(candidate.source)) {View on GitHub (pinned to 01804a7531)
Solutions
- Refresh the Codex session catalog and re-pick the threadId from a current page.
- Confirm the target is an interactive (non-archived) Codex session via `codex` CLI or app-server.
- If the session was archived, restore or re-create it before retrying.
Defensive patterns
Strategy: validation
Validate before calling
const fresh = await control.listPage({ limit: 100 });
const exists = fresh.sessions.some((s) => s.threadId === targetThreadId);
if (!exists) {
// tell the user the session is gone and stop
} Try / catch
try {
await requireCatalogEligibleThread(control, threadId);
} catch (error) {
if (error instanceof CatalogParamsError && /not a non-archived interactive/.test(error.message)) {
// refresh catalog, reselect, or inform user the session is unavailable
}
throw error;
} Prevention
- Always re-select the threadId from a freshly listed catalog page before a mutating action.
- Treat a stale threadId as 'session no longer available' rather than retrying blindly.
When it happens
Trigger: Calling continue/archive/terminal resume with a threadId that does not exist on the app-server, is archived, belongs to a non-interactive source, or was deleted between catalog list and action.
Common situations: Stale threadId copied from an old catalog page; the session was archived by another client or CLI in the meantime; the thread is a non-interactive/internal Codex thread type.
Related errors
- Codex session catalog hostId is invalid
- paired node does not permit Codex session continuation
- Codex session is archived on the paired node
- Codex session is not a non-archived interactive Codex sessio
- Codex session is active on the paired node; wait for it to f
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/60841fe32b3f5f36.
Report an issue: GitHub.