jackwener/OpenCLI · error · CommandExecutionError

Malformed ChatGPT conversation network payload for ${entryCo

Error message

Malformed ChatGPT conversation network payload for ${entryConversationId || 'unknown conversation'}.

What it means

Thrown when scanning captured network entries for a Deep Research conversation: an entry whose URL matches backend-api/conversation/<id> has no parseable response body. The library needs the JSON conversation payload from that network entry to extract results.

Source

Thrown at clis/chatgpt/utils.js:1599

    candidates.sort((a, b) => deepResearchCandidateScore(b) - deepResearchCandidateScore(a));
    return candidates[0] || null;
}

function conversationIdFromBackendConversationUrl(url) {
    const match = String(url || '').match(/\/backend-api\/conversation\/([^/?#]+)/);
    return match?.[1] ? decodeURIComponent(match[1]) : '';
}

function extractDeepResearchFromNetworkEntries(entries, { expectedConversationId = '' } = {}) {
    const candidates = [];
    for (const entry of Array.isArray(entries) ? entries : []) {
        const url = String(entry?.url || '');
        if (!/\/backend-api\/conversation\//.test(url)) continue;
        const entryConversationId = conversationIdFromBackendConversationUrl(url);
        if (expectedConversationId && entryConversationId !== expectedConversationId) continue;
        const body = parseJsonMaybe(entry?.responsePreview) || parseJsonMaybe(entry?.body) || null;
        if (!body) {
            throw new CommandExecutionError(`Malformed ChatGPT conversation network payload for ${entryConversationId || 'unknown conversation'}.`);
        }
        const extracted = extractDeepResearchFromConversationPayload(body, { expectedConversationId });
        if (extracted) {
            candidates.push({
                ...extracted,
                method: extracted.status === 'completed'
                    ? 'network-conversation-widget-state'
                    : 'network-conversation-widget-progress',
                networkUrl: url,
            });
        }
    }
    candidates.sort((a, b) => deepResearchCandidateScore(b) - deepResearchCandidateScore(a));
    return candidates[0] || null;
}

function conversationIdFromUrl(url) {
    const match = String(url || '').match(/\/c\/([a-zA-Z0-9_-]+)/);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Ensure network capture records response bodies (responsePreview/body) for backend-api/conversation requests
  2. Check the entry body is JSON and not an HTML error page or empty 204/304 response
  3. Re-run the request so the network entry is captured fresh, or extract via the page payload path instead
  4. Increase capture buffer/preview size if the body is being truncated

Example fix

// before
const body = parseJsonMaybe(entry.responsePreview);
await extractDeepResearchFromConversationPayload(body, { expectedConversationId });
// after
const body = parseJsonMaybe(entry?.responsePreview) || parseJsonMaybe(entry?.body);
if (!body) throw new Error('conversation network entry had no JSON body; re-capture with bodies enabled');
await extractDeepResearchFromConversationPayload(body, { expectedConversationId });
Defensive patterns

Strategy: validation

Validate before calling

const body = parseJsonMaybe(entry?.responsePreview) || parseJsonMaybe(entry?.body);
if (!body || !body.mapping) throw new Error('network entry has no usable conversation JSON — re-capture with response bodies');

Type guard

function hasResponseBody(e) { return typeof e === 'object' && e !== null && (typeof e.responsePreview === 'string' || typeof e.body === 'string'); }

Try / catch

try {
  await waitForChatGPTDeepResearchResult(/* ... */);
} catch (e) {
  if (String(e.message).startsWith('Malformed ChatGPT conversation network payload')) {
    // retry capture or extract from the page payload instead
  } else throw e;
}

Prevention

When it happens

Trigger: A network entry matching the conversation URL was recorded but both entry.responsePreview and entry.body are missing, empty, or unparseable JSON (parseJsonMaybe returns null).

Common situations: Response body streaming not captured (response body already consumed or preview truncated); binary/HTML error page recorded instead of JSON; HAR export with response bodies stripped; navigation cleared the buffer mid-response.

Understand the failure class

Related errors


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