Mintplex-Labs/anything-llm · error · Error
Invalid response body returned from GiteeAI: ${JSON.stringif
Error message
Invalid response body returned from GiteeAI: ${JSON.stringify(result.output)} What it means
Thrown after a successful HTTP call when the response body is structurally invalid: result.output has no `choices` property, or the choices array is empty. Unlike the catch wrapper, this means the server answered without throwing but the body is not a usable OpenAI-format completion. The full response is JSON-stringified into the message for debugging.
Source
Thrown at server/utils/AiProviders/giteeai/index.js:139
async getChatCompletion(messages = null, { temperature = 0.7 }) {
const result = await LLMPerformanceMonitor.measureAsyncFunction(
this.openai.chat.completions
.create({
model: this.model,
messages,
temperature,
})
.catch((e) => {
throw new Error(e.message);
})
);
if (
!result?.output?.hasOwnProperty("choices") ||
result?.output?.choices?.length === 0
)
throw new Error(
`Invalid response body returned from GiteeAI: ${JSON.stringify(result.output)}`
);
return {
textResponse: this.#parseReasoningFromResponse(result.output.choices[0]),
metrics: {
prompt_tokens: result.output.usage.prompt_tokens || 0,
completion_tokens: result.output.usage.completion_tokens || 0,
total_tokens: result.output.usage.total_tokens || 0,
outputTps: result.output.usage.completion_tokens / result.duration,
duration: result.duration,
model: this.model,
provider: this.className,
timestamp: new Date(),
},
};
}
View on GitHub (pinned to 526360e320)
Solutions
- Read the JSON.stringify(result.output) embedded in the message — it shows exactly what Gitee returned
- If it contains an `error` field, address that cause (content policy, model unavailable)
- Retry once in case of a transient gateway/partial response
- Check Gitee AI status/changelog for response-schema changes
Example fix
// before
if (!result?.output?.hasOwnProperty('choices') || result?.output?.choices?.length === 0)
throw new Error(`Invalid response body returned from GiteeAI: ${JSON.stringify(result.output)}`);
// after (surface a structured, type-safe error instead of a stringly one)
if (!result?.output?.choices?.length)
throw new GiteeResponseError('No choices in GiteeAI response', result.output); Defensive patterns
Strategy: type-guard
Type guard
function isOpenAiCompletion(payload) {
return payload != null
&& Array.isArray(payload.choices)
&& payload.choices.length > 0
&& payload.choices[0]?.message != null;
} Try / catch
const result = await llm.getChatCompletion(messages, { temperature }).catch(async (e) => {
if (/Invalid response body returned from GiteeAI/.test(e.message)) {
// inspect the stringified body in the message, classify (content filter vs outage)
if (/content_filter|safety/i.test(e.message)) throw new ContentFilterError(e.message);
throw new UpstreamFormatError(e.message);
}
throw e;
}); Prevention
- Validate the response shape with a type guard before reading choices
- Retry once on transient gateway/empty-body responses
- Log the raw body (as this error does) so content-filter vs outage is distinguishable
When it happens
Trigger: Gitee AI returns 200 with a body missing `choices` — e.g. an error object {error: ...}, an HTML error page parsed as text, a content-filter block with no choices, or a schema change on Gitee's side. The `.hasOwnProperty('choices')` / `choices.length === 0` check then trips.
Common situations: Gitee AI content policy rejecting the prompt (returns an object without choices); upstream model crashed and Gitee returned a status envelope; partial/gateway response; API version drift where the response shape changed.
Related errors
- e.message
- ${e.message}
- CometAPI chat: ${this.model} is not valid for chat completio
- ${e.message}
- DeepSeek chat: ${this.model} is not valid for chat completio
AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13).
Data as JSON: /api/errors/b46103d05e151520.
Report an issue: GitHub.