Mintplex-Labs/anything-llm · error · Error

e.message

Error message

e.message

What it means

Identical re-wrap anti-pattern in Novita's getChatCompletion: .catch flattens any upstream Novita API error to Error(e.message), discarding status/type. On a choices-less successful response Novita (like Mistral) returns null rather than throwing.

Source

Thrown at server/utils/AiProviders/novita/index.js:236

      },
    ];
  }

  async getChatCompletion(messages = null, { temperature = 0.7 }) {
    if (!(await this.isValidChatCompletionModel(this.model)))
      throw new Error(
        `Novita chat: ${this.model} is not valid for chat completion!`
      );

    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
    )
      return null;

    return {
      textResponse: result.output.choices[0].message.content,
      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,

View on GitHub (pinned to 526360e320)

Solutions

  1. Inspect the message for the upstream cause.
  2. If timeout-like, raise defaultTimeout or choose a faster model.
  3. If auth/quota text, verify NOVITA_LLM_API_KEY and plan limits.
  4. Retry with backoff for transient text.

Example fix

// before
defaultTimeout = 3_000;  // too low for slow models
.catch((e) => { throw new Error(e.message); })

// after
defaultTimeout = 30_000;
.catch((e) => {
  const err = new Error(`Novita chat failed (${e?.status}): ${e.message}`);
  err.cause = e; err.status = e?.status;
  throw err;
})
Defensive patterns

Strategy: retry

Try / catch

try {
  await llm.getChatCompletion(messages, { temperature });
} catch (e) {
  const msg = e.message || '';
  if (/timeout|etimedout|econnaborted/i.test(msg)) { /* raise defaultTimeout or pick a faster model */ }
  else if (/429|rate/i.test(msg)) { /* backoff */ }
  else if (/401|api key/i.test(msg)) { /* rotate key */ }
}

Prevention

When it happens

Trigger: Any upstream failure from the Novita chat completion call: 401, 429, 400, timeout, or 5xx — surfaced only as the message string. Note the 3000ms defaultTimeout can also produce timeout errors here.

Common situations: Invalid Novita key; rate/quota limits; the 3s defaultTimeout firing on slow models (timeout surfaces as an error message here); transient outage.

Related errors


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