{"record":{"id":"588008d9318a00cb","repo":"decolua/9router","slug":"codewhisperertomessages-produced-0-messages-chec","errorCode":null,"errorMessage":"codeWhispererToMessages produced 0 messages — check request body","messagePattern":"codeWhispererToMessages produced 0 messages — check request body","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mitm/handlers/kiro.js","lineNumber":501,"sourceCode":" * @param {http.ServerResponse} res - HTTP response to Kiro IDE  \n * @param {Buffer} bodyBuffer - Request body buffer\n * @param {string} mappedModel - Model name after MITM alias mapping\n */\nasync function intercept(req, res, bodyBuffer, mappedModel) {\n  try {\n    // Detect and handle binary data (e.g., continuation requests with EventStream frames)\n    if (isBinaryEventStream(bodyBuffer)) {\n      // Binary EventStream requests are typically continuation/streaming frames\n      // that don't contain model info - pass them through directly to avoid JSON.parse crash\n      throw new Error(`Binary EventStream format detected (${bodyBuffer.length}B) - request should use passthrough instead of intercept`);\n    }\n    \n    const body = JSON.parse(bodyBuffer.toString());\n\n    // 1 + 2: CodeWhisperer → OpenAI messages + tools\n    const messages = codeWhispererToMessages(body);\n    if (messages.length === 0) {\n      throw new Error(\"codeWhispererToMessages produced 0 messages — check request body\");\n    }\n\n    const tools = extractTools(body);\n\n    const openaiBody = {\n      model: mappedModel,\n      messages,\n      stream: true,\n      // Forward tools so Claude uses structured tool_calls instead of XML text fallback\n      ...(tools.length > 0 && { tools, tool_choice: \"auto\" }),\n    };\n\n    // 3: Forward to 9router\n    const routerRes = await fetchRouter(openaiBody, \"/v1/chat/completions\", req.headers);\n\n    // 4 + 5: Re-encode response as AWS EventStream binary using standard pipeline\n    const state = initKiroState(mappedModel);\n","sourceCodeStart":483,"sourceCodeEnd":519,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/mitm/handlers/kiro.js#L483-L519","documentation":"After JSON-parsing the Kiro/CodeWhisperer request, intercept() converts it to OpenAI-style messages via codeWhispererToMessages(). If that converter yields an empty array, there is nothing to forward upstream, so the handler throws this error rather than sending a doomed request. It signals the request body had a shape the translator did not recognize or contained no conversation content.","triggerScenarios":"POSTing to the Kiro intercept endpoint a body that JSON-parses but has no recognizable CodeWhisperer conversation fields — e.g. `{}`, an empty `conversationState`, missing `currentMessage`/history entries, or a body whose structure changed in a newer client version the translator does not yet map.","commonSituations":"Client app updated and changed the CodeWhisperer request schema ahead of the proxy's translator; a tool sent an empty/keepalive JSON body through the intercept path; manual curl tests with hand-written minimal bodies; a non-Kiro request mistakenly routed to the Kiro handler.","solutions":["Log the parsed body (JSON.stringify(body)) and compare its shape against what codeWhispererToMessages expects in the translator","Ensure the request includes populated conversation state (history + current message) before routing to intercept","Update the proxy/translator to the client's current CodeWhisperer schema if the client was upgraded","Verify the request is actually a Kiro/CodeWhisperer conversation and not another tool's request misrouted to this handler"],"exampleFix":"// before\nconst body = JSON.parse(rawBody);\nawait intercept(req, res, rawBody, model);\n// after\nconst body = JSON.parse(rawBody);\nconst msgs = codeWhispererToMessages(body);\nif (!msgs.length) {\n  console.error('untranslated body:', JSON.stringify(body).slice(0, 500));\n  return res.status(400).end('empty conversation');\n}","handlingStrategy":"validation","validationCode":"const msgs = codeWhispererToMessages(body);\nif (!Array.isArray(msgs) || msgs.length === 0) {\n  return res.status(400).json({ error: 'Request contained no translatable conversation' });\n}","typeGuard":"function hasTranslatableMessages(body) {\n  const msgs = codeWhispererToMessages(body);\n  return Array.isArray(msgs) && msgs.length > 0;\n}","tryCatchPattern":"try {\n  await intercept(req, res, bodyBuffer, mappedModel);\n} catch (e) {\n  if (e.message.includes('produced 0 messages')) {\n    console.error('Body failed translation:', bodyBuffer.toString().slice(0, 500));\n    return res.status(400).end();\n  }\n  throw e;\n}","preventionTips":["Log and inspect the parsed body whenever translation fails","Validate the request has conversation content before routing to the Kiro handler","Keep the translator in sync with the client's CodeWhisperer schema version","Reject empty/keepalive JSON bodies at the edge"],"tags":["kiro","translation","empty-payload","mitm"],"backgroundTag":"empty-translated-messages","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}