Mintplex-Labs/anything-llm · error · Error

xAI chat: ${this.model} is not valid for chat completion!

Error message

xAI chat: ${this.model} is not valid for chat completion!

What it means

Thrown by XAiLLM.getChatCompletion when this.isValidChatCompletionModel(this.model) is false. NOTE: in the current implementation isValidChatCompletionModel unconditionally returns true, so this branch is effectively dead code and the throw is not reachable without overriding that method. If it ever fires, it means the guard was changed to actually validate and the configured model failed.

Source

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

    attachments = [], // This is the specific attachment for only this prompt
  }) {
    const prompt = {
      role: "system",
      content: `${systemPrompt}${this.#appendContext(contextTexts)}`,
    };
    return [
      prompt,
      ...formatChatHistory(chatHistory, this.#generateContent),
      {
        role: "user",
        content: this.#generateContent({ userPrompt, attachments }),
      },
    ];
  }

  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

View on GitHub (pinned to 526360e320)

Solutions

  1. If you genuinely hit this, inspect whether isValidChatCompletionModel was overridden by a subclass or monkeypatch.
  2. Set XAI_LLM_MODEL_PREF to a real grok model id (e.g. 'grok-beta', 'grok-2-latest') so any future validator passes.
  3. If adding real validation, mirror the MODEL_MAP.get('xai', modelName) lookup used by promptWindowLimit rather than leaving an always-true stub.

Example fix

// before
isValidChatCompletionModel(_modelName = "") {
  return true;
}

// after (if you actually want validation)
isValidChatCompletionModel(modelName = "") {
  return MODEL_MAP.get("xai", modelName) != null;
}
Defensive patterns

Strategy: validation

Validate before calling

// Currently a no-op: isValidChatCompletionModel always returns true.
// If you add real validation, check before calling:
const ok = llm.isValidChatCompletionModel(llm.model);
if (!ok) throw new Error(`xAI model ${llm.model} rejected by validator`);

Type guard

/** @param {string} m */
function isLikelyXaiModel(m) {
  return typeof m === 'string' && /^grok/i.test(m);
}

Try / catch

try {
  await llm.getChatCompletion(messages, { temperature });
} catch (e) {
  if (/is not valid for chat completion/.test(e.message)) {
    // only reachable if isValidChatCompletionModel was overridden — audit subclass
  }
  throw e;
}

Prevention

When it happens

Trigger: Not reachable given isValidChatCompletionModel() { return true; } at xai/index.js:65. Would only fire if a subclass or future edit makes the validator reject this.model (e.g. checking MODEL_MAP for 'xai').

Common situations: Developers see this string in source search and assume xAI validates models; it does not. Practically the error never surfaces, so encountering it implies a custom subclass that overrode the validator.

Related errors


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