Mintplex-Labs/anything-llm · error · Error

${e.message}

Error message

${e.message}

What it means

Re-thrown from the .catch on this.openai.chat.completions.create inside getChatCompletion. Any rejection from the xAI OpenAI-compatible endpoint is flattened to a new Error carrying only e.message, discarding the original status code, error type, headers, and stack. The text is whatever the OpenAI SDK or the upstream API returned.

Source

Thrown at server/utils/AiProviders/xai/index.js:132

      },
    ];
  }

  async getChatCompletion(messages = null, { temperature = 0.7 }) {
    if (!this.isValidChatCompletionModel(this.model))
      throw new Error(
        `xAI 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. Read e.message: '401'/'Unauthorized' -> fix XAI_LLM_API_KEY; 'model_not_found' -> fix XAI_LLM_MODEL_PREF; 'rate_limit' -> back off.
  2. Wrap the getChatCompletion call in try/catch and branch on substring of the message, since the status code is no longer on the thrown error.
  3. If you need the status code, call this.openai.chat.completions.create directly or patch the .catch to rethrow e (the original) instead of new Error(e.message).
  4. Retry transient 5xx/429 with exponential backoff; surface permanent 4xx to the user.

Example fix

// before (loses status/type)
.catch((e) => { throw new Error(e.message); })

// after (preserve original error for callers)
.catch((e) => {
  const err = new Error(e.message);
  err.status = e.status;
  err.type = e.error?.type;
  err.cause = e;
  throw err;
})
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight a minimal models list call to verify auth/endpoint
try {
  await llm.openai.models.list();
} catch (e) {
  throw new Error(`xAI preflight failed: ${e.message}`);
}

Try / catch

try {
  const res = await llm.getChatCompletion(messages, { temperature });
} catch (e) {
  const msg = e.message;
  if (/401|unauthorized|api.key/i.test(msg)) handleAuth();
  else if (/rate.limit|429/i.test(msg)) backoff();
  else if (/model_not_found|404/i.test(msg)) handleBadModel();
  else throw e;
}

Prevention

When it happens

Trigger: 401 invalid/revoked XAI_LLM_API_KEY; 404 model not found (bad XAI_LLM_MODEL_PREF); 429 rate limit; 5xx from api.x.ai; network timeout or DNS failure; malformed request body from unsupported message content.

Common situations: Key rotated but not redeployed; switching to a grok model id that does not exist yet; burst traffic hitting xAI rate limits; intermittent 5xx during xAI incidents; sending attachments in a format grok rejects.

Related errors


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