Mintplex-Labs/anything-llm · error · Error

Invalid response body returned from DeepSeek: ${JSON.stringi

Error message

Invalid response body returned from DeepSeek: ${JSON.stringify(result.output)}

What it means

Thrown after a successful API call when the response object lacks a 'choices' property or has an empty choices array. This indicates DeepSeek returned a 200 response with an unexpected/empty body — not a standard error. The full response is JSON-stringified into the message for debugging. Unlike the Cohere/CometAPI providers which return null in this case, DeepSeek treats it as a hard error.

Source

Thrown at server/utils/AiProviders/deepseek/index.js:119

      );

    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 DeepSeek: ${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

  1. Inspect the JSON-stringified result.output in the error message — it reveals exactly what DeepSeek returned.
  2. If the body contains an error/filter field, adjust the prompt to avoid triggering content filters.
  3. Check the DeepSeek API changelog for response schema changes.
  4. Consider catching this specific error and returning null (as Cohere/CometAPI do) for graceful degradation.

Example fix

// before
if (
  !result?.output?.hasOwnProperty("choices") ||
  result?.output?.choices?.length === 0
)
  throw new Error(
    `Invalid response body returned from DeepSeek: ${JSON.stringify(result.output)}`
  );

// after — degrade gracefully like sibling providers
if (
  !result?.output?.hasOwnProperty("choices") ||
  result?.output?.choices?.length === 0
) {
  this.log(`Empty choices in DeepSeek response: ${JSON.stringify(result.output)}`);
  return null;
}
Defensive patterns

Strategy: try-catch

Type guard

/** Narrows a well-formed DeepSeek/OpenAI completion response. */
function hasValidChoices(output) {
  return (
    output != null &&
    typeof output === 'object' &&
    Array.isArray(output.choices) &&
    output.choices.length > 0
  );
}

Try / catch

try {
  return await deepseek.getChatCompletion(messages, { temperature });
} catch (e) {
  if (/Invalid response body returned from DeepSeek/i.test(e.message)) {
    console.error('DeepSeek returned an unexpected body:', e.message);
    return null; // degrade gracefully instead of surfacing the error
  }
  throw e;
}

Prevention

When it happens

Trigger: DeepSeek returns a valid HTTP 200 but with an empty or malformed body (e.g. content-filtered response with no choices); the response shape changes due to a DeepSeek API update; the model returns only an error field without choices; usage is undefined causing downstream issues masked as a choices problem.

Common situations: Content policy triggers causing DeepSeek to omit choices; API version mismatch where the response schema shifted; rare server-side bugs returning incomplete payloads; reasoning_content-only responses on some model variants.

Related errors


AI-assisted analysis of Mintplex-Labs/anything-llm@526360e320 (2026-08-13). Data as JSON: /api/errors/f2b9285c24dfdaf5. Report an issue: GitHub.