{"record":{"id":"9138f01c2e043ca0","repo":"jackwener/OpenCLI","slug":"malformed-chatgpt-conversation-payload-for-deep-re","errorCode":null,"errorMessage":"Malformed ChatGPT conversation payload for Deep Research extraction.","messagePattern":"Malformed ChatGPT conversation payload for Deep Research extraction\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/chatgpt/utils.js","lineNumber":1531,"sourceCode":"    const report = normalizeDeepResearchText(parts.filter((part) => typeof part === 'string').join('\\n\\n'));\n    if (looksLikeDeepResearchReport(report)) {\n        return {\n            status: 'completed',\n            report,\n            html: '',\n            method: source,\n            sources: extractDeepResearchSourcesFromReportMessage(reportMessage),\n            widgetStatus: String(widgetStateObject.status || ''),\n            reportMessageId: String(reportMessage?.id || ''),\n            reportLength: report.length,\n        };\n    }\n    return buildDeepResearchProgressResult(widgetStateObject, pickFirstObject(responseMetadata), source);\n}\n\nfunction extractDeepResearchFromConversationPayload(payload, { expectedConversationId = '' } = {}) {\n    if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {\n        throw new CommandExecutionError('Malformed ChatGPT conversation payload for Deep Research extraction.');\n    }\n    const payloadConversationId = String(payload.conversation_id || payload.conversationId || payload.id || '').trim();\n    if (expectedConversationId && payloadConversationId && payloadConversationId !== expectedConversationId) {\n        throw new CommandExecutionError(\n            `ChatGPT conversation payload id mismatch: expected ${expectedConversationId}, got ${payloadConversationId}.`,\n        );\n    }\n    const mapping = payload?.mapping && typeof payload.mapping === 'object' ? payload.mapping : {};\n    if (!payload.mapping || typeof payload.mapping !== 'object' || Array.isArray(payload.mapping)) {\n        throw new CommandExecutionError('Malformed ChatGPT conversation payload for Deep Research extraction: missing mapping.');\n    }\n    const candidates = [];\n    for (const [messageId, node] of Object.entries(mapping)) {\n        const message = node?.message || {};\n        const metadata = message?.metadata || {};\n        const sdk = metadata?.chatgpt_sdk || {};\n        const responseMetadata = pickFirstObject(\n            sdk?.response_metadata,","sourceCodeStart":1513,"sourceCodeEnd":1549,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/chatgpt/utils.js#L1513-L1549","documentation":"extractDeepResearchFromConversationPayload validates the conversation payload before extracting Deep Research progress. A payload that is not a non-array object (null, a string, a number, or an Array) cannot contain conversation fields or a message mapping, so the library throws immediately rather than returning a partial result.","triggerScenarios":"Calling extractDeepResearchFromConversationPayload with a null/undefined payload, a JSON string not yet parsed, an array of payloads, or an HTTP response body that failed JSON parsing.","commonSituations":"API returning an error page/HTML string instead of JSON; response.json() misused or response.text() passed directly; fetch following a redirect to a non-JSON endpoint; passing an array of conversation chunks instead of a single payload object.","solutions":["Ensure the fetch response is awaited with .json() before passing it in, and check res.ok first.","Parse strings with JSON.parse and validate the result is a non-array object before extraction.","Wrap the call in try-catch and surface a user-friendly 'unexpected ChatGPT response' message.","Verify the endpoint actually returns the conversation payload shape ({conversation_id, mapping, ...})."],"exampleFix":"// before\nconst result = extractDeepResearchFromConversationPayload(await res.text());\n// after\nconst payload = await res.json();\nif (!payload || typeof payload !== 'object' || Array.isArray(payload)) throw new Error('Unexpected ChatGPT response');\nconst result = extractDeepResearchFromConversationPayload(payload);","handlingStrategy":"type-guard","validationCode":"function assertConversationPayload(p) {\n  if (!p || typeof p !== 'object' || Array.isArray(p)) throw new Error('payload must be a non-array object');\n  if (!p.mapping || typeof p.mapping !== 'object') throw new Error('payload missing mapping');\n}","typeGuard":"const isConversationPayload = (p) =>\n  !!p && typeof p === 'object' && !Array.isArray(p) &&\n  typeof p.mapping === 'object' && p.mapping !== null && !Array.isArray(p.mapping);","tryCatchPattern":"let payload;\ntry {\n  payload = await res.json();\n} catch (e) {\n  throw new Error(`ChatGPT returned non-JSON body: ${e.message}`);\n}\ntry {\n  return extractDeepResearchFromConversationPayload(payload, { expectedConversationId });\n} catch (err) {\n  if (String(err.message).includes('Malformed ChatGPT conversation payload')) {\n    return { progress: null, reason: 'unexpected payload shape' };\n  }\n  throw err;\n}","preventionTips":["Always call res.json() (never pass raw text) before extraction","Check res.ok and content-type before parsing","Validate payload shape with a type guard prior to extraction","Ensure you pass one payload object, not an array of chunks"],"tags":["validation","deep-research","payload-parsing"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}