musistudio/claude-code-router · error · Error

OpenAI resolve retrieval returned no assistant message.

Error message

OpenAI resolve retrieval returned no assistant message.

What it means

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.

Source

Thrown at packages/core/src/mcp/toolhub-mcp.ts:1684

                code: {
                  type: "string",
                  description: "TypeScript workflow sketch that references ToolHub tools."
                }
              },
              required: ["code"],
              additionalProperties: false
            }
          }
        }
      ],
      tool_choice: "auto"
    } as OpenAI.Chat.Completions.ChatCompletionCreateParamsNonStreaming, {
      timeout: timeoutMs
    });

    const message = response.choices[0]?.message;
    if (!message) {
      throw new Error("OpenAI resolve retrieval returned no assistant message.");
    }
    const content = typeof message.content === "string" ? message.content : "";
    const toolCalls = (message.tool_calls ?? [])
      .map((toolCall, index) => {
        const rawToolCall = toolCall as unknown as { function?: unknown };
        const functionCall = isRecord(rawToolCall.function) ? rawToolCall.function : {};
        return {
          id: toolCall.id || `tool_call_${index}`,
          type: "function" as const,
          function: {
            arguments: typeof functionCall.arguments === "string" ? functionCall.arguments : "",
            name: typeof functionCall.name === "string" ? functionCall.name : ""
          }
        };
      })
      .filter((toolCall) => toolCall.function.name.length > 0);
    if (!content && toolCalls.length === 0) {
      throw new Error("OpenAI resolve retrieval returned no assistant content or tool calls.");

View on GitHub (pinned to 99f24806c6)

Solutions

  1. Verify TOOLHUB_OPENAI_MODEL is valid for the endpoint at TOOLHUB_OPENAI_BASE_URL
  2. Test the endpoint directly with curl to confirm responses include choices[0].message in OpenAI format
  3. If using a gateway, upgrade or configure it for OpenAI chat-completions compatibility

Example fix

// before
TOOLHUB_OPENAI_BASE_URL=https://my-proxy.example.com/v1

# after: confirm the endpoint returns OpenAI-shaped responses
curl $TOOLHUB_OPENAI_BASE_URL/chat/completions -H "Authorization: Bearer $KEY" -d '{"model":"'$TOOLHUB_OPENAI_MODEL'","messages":[{"role":"user","content":"hi"}]}'
Defensive patterns

Strategy: validation

Validate before calling

// Smoke-test the endpoint shape before resolving
const r = await fetch(`${baseURL}/chat/completions`, { method: "POST", headers: { Authorization: `Bearer ${key}` }, body: JSON.stringify({ model, messages: [{ role: "user", content: "ping" }] }) });
const json = await r.json();
if (!json.choices?.[0]?.message) throw new Error("Endpoint is not OpenAI-compatible");

Type guard

const hasAssistantMessage = (j: any): j is { choices: { message: object }[] } =>
  Boolean(j?.choices?.[0]?.message);

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of musistudio/claude-code-router@99f24806c6 (2026-08-27). Data as JSON: /api/errors/55008a0e1a888130. Report an issue: GitHub.