{"record":{"id":"12a4cd47938a8b9b","repo":"openclaw/openclaw","slug":"codex-cli-resume-returned-an-invalid-payload","errorCode":null,"errorMessage":"Codex CLI resume returned an invalid payload.","messagePattern":"Codex CLI resume returned an invalid payload\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extensions/codex/src/node-cli-sessions.ts","lineNumber":172,"sourceCode":"  prompt: string;\n  cwd?: string;\n  timeoutMs?: number;\n}): Promise<CodexCliSessionResumeResult> {\n  const raw = await params.runtime.nodes.invoke({\n    nodeId: params.nodeId,\n    command: CODEX_CLI_SESSION_RESUME_COMMAND,\n    params: {\n      sessionId: params.sessionId,\n      prompt: params.prompt,\n      cwd: params.cwd,\n      timeoutMs: params.timeoutMs,\n    },\n    timeoutMs: (params.timeoutMs ?? DEFAULT_RESUME_TIMEOUT_MS) + 5_000,\n    scopes: [\"operator.write\"],\n  });\n  const payload = unwrapNodeInvokePayload(raw);\n  if (!isRecord(payload) || payload.ok !== true || typeof payload.text !== \"string\") {\n    throw new Error(\"Codex CLI resume returned an invalid payload.\");\n  }\n  return {\n    ok: true,\n    sessionId: typeof payload.sessionId === \"string\" ? payload.sessionId : params.sessionId,\n    text: payload.text,\n  };\n}\n\nexport function formatCodexCliSessions(params: {\n  node: CodexCliSessionNodeInfo;\n  result: CodexCliSessionsListResult;\n}): string {\n  if (params.result.sessions.length === 0) {\n    return `No Codex CLI sessions returned from ${formatCodexDisplayText(formatNodeLabel(params.node))}.`;\n  }\n  return [\n    `Codex CLI sessions on ${formatCodexDisplayText(formatNodeLabel(params.node))}:`,\n    ...params.result.sessions.map((session) => {","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/codex/src/node-cli-sessions.ts#L154-L190","documentation":"The resumeCodexCliSessionOnNode node invoke returned a payload that is not a record, or whose ok !== true, or whose text is not a string. resumeCodexCliSessionOnNode unwraps the node invoke result and requires a success envelope { ok: true, text: string, sessionId? }; any deviation is treated as a malformed remote response.","triggerScenarios":"The remote node's resume handler returned an error object { ok: false, error }, a non-object, or a success object missing the text field. unwrapNodeInvokePayload + the record/ok/text guards at node-cli-sessions.ts:172 reject it.","commonSituations":"The remote codex exec resume failed and the node reported ok:false; a node-side serialization bug dropped the text field; version mismatch between the invoking plugin and the node's resume handler.","solutions":["Inspect the node-side resume logs to see why it returned ok !== true (the underlying error is usually there).","Confirm the node's resume handler emits { ok: true, text: string, sessionId? } on success.","Retry the resume once transient node errors are ruled out.","Update the node plugin so the resume handler returns the contract envelope."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":null,"typeGuard":"function isValidResumePayload(p: unknown): p is { ok: true; text: string; sessionId?: string } {\n  return typeof p === 'object' && p !== null && (p as any).ok === true && typeof (p as any).text === 'string';\n}","tryCatchPattern":"try {\n  const raw = await runtime.nodes.invoke({ ... });\n  const payload = unwrapNodeInvokePayload(raw);\n  if (!isValidResumePayload(payload)) throw new Error('invalid resume payload');\n} catch (e) {\n  // inspect node-side resume logs for the real ok:false cause\n  throw e;\n}","preventionTips":["Ensure the node resume handler returns { ok: true, text, sessionId? } on success and a clear error on failure.","Version-match the invoking plugin with the node plugin's resume handler.","Log unwrapNodeInvokePayload output at debug level to catch envelope drift."],"tags":["codex","cli-sessions","resume","node-invoke","validation"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}