jackwener/OpenCLI · error · CommandExecutionError

Codex sidebar extraction returned an invalid payload.

Error message

Codex sidebar extraction returned an invalid payload.

What it means

readConversationProjects runs an in-page script (collectCodexProjectsFromDocument) in the Codex web UI to extract the conversation sidebar rows, unwrapping the evaluate result. If the result is not an array the DOM extraction contract is broken, so opencli throws this CommandExecutionError instead of operating on bad data.

Source

Thrown at clis/codex/_actions.js:86

    return null;
}

export function findActiveCodexConversation(projects) {
    const active = [];
    for (const project of projects || []) {
        for (const conversation of project.conversations || []) {
            if (conversation.active) {
                active.push({ project, conversation });
            }
        }
    }
    return active.length === 1 ? active[0] : null;
}

export async function readConversationProjects(page) {
    const projects = unwrapEvaluateResult(await page.evaluate(`(${collectCodexProjectsFromDocument.toString()})()`));
    if (!Array.isArray(projects)) {
        throw new CommandExecutionError('Codex sidebar extraction returned an invalid payload.');
    }
    return projects;
}

export async function resolveActionConversation(page, kwargs) {
    const selected = await openCodexConversation(page, kwargs);
    const projects = await readConversationProjects(page);
    const resolved = selected
        ? findCodexConversation(projects, selected)
        : findActiveCodexConversation(projects);
    if (!resolved) {
        const hint = hasConversationTarget(kwargs)
            ? 'The selected Codex conversation was not visible after selection.'
            : 'Pass --project/--conversation/--index/--thread-id, or keep the active conversation visible in the sidebar.';
        throw new CommandExecutionError('Could not resolve a stable Codex conversation identity.', hint);
    }
    if (!resolved.conversation.threadId) {
        throw new CommandExecutionError(

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Confirm Codex Desktop is running and the app page is fully loaded with the sidebar visible
  2. Log in / re-establish the session if the page shows a login screen
  3. Update opencli so its extraction selectors match the current Codex UI
  4. Retry after the page finishes loading

Example fix

// before
const projects = await readConversationProjects(page); // throws if page still loading
// after
await page.waitForSelector('[data-sidebar]', { timeout: 10000 });
const projects = await readConversationProjects(page);
Defensive patterns

Strategy: type-guard

Validate before calling

await page.waitForSelector('.sidebar', { timeout: 10000 });
const projects = unwrapEvaluateResult(
  await page.evaluate(`(${collectCodexProjectsFromDocument.toString()})()`)
);
if (!Array.isArray(projects)) throw new Error('Sidebar not ready; aborting');

Type guard

function isProjectArray(v) {
  return Array.isArray(v) && v.every(p => p && typeof p.project === 'string' && Array.isArray(p.conversations));
}

Try / catch

try {
  const projects = await readConversationProjects(page);
} catch (e) {
  if (e instanceof CommandExecutionError && e.message.includes('invalid payload')) {
    await page.reload();
    await page.waitForSelector('.sidebar');
    // retry once
  } else throw e;
}

Prevention

When it happens

Trigger: page.evaluate returns null/undefined/non-array because the sidebar is absent, the page is still loading, the user is logged out, or collectCodexProjectsFromDocument's selectors no longer match after a Codex UI change.

Common situations: Codex Desktop not running / page on an error or login screen, sidebar collapsed or empty, Codex deployed a DOM redesign that breaks the extraction script.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/5c9206e20f992e2e. Report an issue: GitHub.