{"record":{"id":"55008a0e1a888130","repo":"musistudio/claude-code-router","slug":"openai-resolve-retrieval-returned-no-assistant-mes","errorCode":null,"errorMessage":"OpenAI resolve retrieval returned no assistant message.","messagePattern":"OpenAI resolve retrieval returned no assistant message\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/mcp/toolhub-mcp.ts","lineNumber":1684,"sourceCode":"                code: {\n                  type: \"string\",\n                  description: \"TypeScript workflow sketch that references ToolHub tools.\"\n                }\n              },\n              required: [\"code\"],\n              additionalProperties: false\n            }\n          }\n        }\n      ],\n      tool_choice: \"auto\"\n    } as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming, {\n      timeout: timeoutMs\n    });\n\n    const message = response.choices[0]?.message;\n    if (!message) {\n      throw new Error(\"OpenAI resolve retrieval returned no assistant message.\");\n    }\n    const content = typeof message.content === \"string\" ? message.content : \"\";\n    const toolCalls = (message.tool_calls ?? [])\n      .map((toolCall, index) => {\n        const rawToolCall = toolCall as unknown as { function?: unknown };\n        const functionCall = isRecord(rawToolCall.function) ? rawToolCall.function : {};\n        return {\n          id: toolCall.id || `tool_call_${index}`,\n          type: \"function\" as const,\n          function: {\n            arguments: typeof functionCall.arguments === \"string\" ? functionCall.arguments : \"\",\n            name: typeof functionCall.name === \"string\" ? functionCall.name : \"\"\n          }\n        };\n      })\n      .filter((toolCall) => toolCall.function.name.length > 0);\n    if (!content && toolCalls.length === 0) {\n      throw new Error(\"OpenAI resolve retrieval returned no assistant content or tool calls.\");","sourceCodeStart":1666,"sourceCodeEnd":1702,"githubUrl":"https://github.com/musistudio/claude-code-router/blob/99f24806c6a2c660b16e53e95211c517448a6c90/packages/core/src/mcp/toolhub-mcp.ts#L1666-L1702","documentation":"Thrown when the OpenAI-compatible chat completion response for ToolHub resolve has no message in choices[0]. It means the HTTP call succeeded (200) but the response body lacks an assistant message — usually an empty choices array or malformed payload from a non-OpenAI-compatible endpoint.","triggerScenarios":"Calling the resolver against a TOOLHUB_OPENAI_BASE_URL whose response shape differs from OpenAI's (missing choices[0].message), or the API returning an empty choices list.","commonSituations":"Pointing baseURL at a local CCR gateway or third-party proxy that returns a non-standard schema; content-filtered responses with empty choices; model name not recognized by the gateway producing degenerate responses.","solutions":["Verify TOOLHUB_OPENAI_MODEL is valid for the endpoint at TOOLHUB_OPENAI_BASE_URL","Test the endpoint directly with curl to confirm responses include choices[0].message in OpenAI format","If using a gateway, upgrade or configure it for OpenAI chat-completions compatibility"],"exampleFix":"// before\nTOOLHUB_OPENAI_BASE_URL=https://my-proxy.example.com/v1\n\n# after: confirm the endpoint returns OpenAI-shaped responses\ncurl $TOOLHUB_OPENAI_BASE_URL/chat/completions -H \"Authorization: Bearer $KEY\" -d '{\"model\":\"'$TOOLHUB_OPENAI_MODEL'\",\"messages\":[{\"role\":\"user\",\"content\":\"hi\"}]}'","handlingStrategy":"validation","validationCode":"// Smoke-test the endpoint shape before resolving\nconst r = await fetch(`${baseURL}/chat/completions`, { method: \"POST\", headers: { Authorization: `Bearer ${key}` }, body: JSON.stringify({ model, messages: [{ role: \"user\", content: \"ping\" }] }) });\nconst json = await r.json();\nif (!json.choices?.[0]?.message) throw new Error(\"Endpoint is not OpenAI-compatible\");","typeGuard":"const hasAssistantMessage = (j: any): j is { choices: { message: object }[] } =>\n  Boolean(j?.choices?.[0]?.message);","tryCatchPattern":null,"preventionTips":["Validate custom base URLs with a chat-completions smoke test at startup","Prefer well-known OpenAI-compatible gateways"],"tags":["openai","toolhub","response-shape","llm"],"backgroundTag":"llm-empty-response-choices","analyzedSha":"99f24806c6a2c660b16e53e95211c517448a6c90","analyzedAt":"2026-08-27T04:11:01.184Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}