Mintplex-Labs/anything-llm · error · Error

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

Error message

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

What it means

Thrown by PPIOLLM.getChatCompletion when isValidChatCompletionModel(this.model) is false. Unlike the static Perplexity list, PPIO calls #syncModels() (which fetches the live /v3/openai/models list, caching to storage/models/ppio) and then checks the model is present — so this fails when the id is not in the freshly synced set.

Source

Thrown at server/utils/AiProviders/ppio/index.js:150

  }

  constructPrompt({
    systemPrompt = "",
    contextTexts = [],
    chatHistory = [],
    userPrompt = "",
    // attachments = [], - not supported
  }) {
    const prompt = {
      role: "system",
      content: `${systemPrompt}${this.#appendContext(contextTexts)}`,
    };
    return [prompt, ...chatHistory, { role: "user", content: userPrompt }];
  }

  async getChatCompletion(messages = null, { temperature = 0.7 }) {
    if (!(await this.isValidChatCompletionModel(this.model)))
      throw new Error(
        `PPIO 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 (
      !Object.prototype.hasOwnProperty.call(result.output, "choices") ||
      result.output.choices.length === 0

View on GitHub (pinned to 526360e320)

Solutions

  1. Inspect the cached list at storage/models/ppio (or call GET https://api.ppinfra.com/v3/openai/models with the key) and set this.model to an id present there.
  2. Delete the stale storage/models/ppio cache so #syncModels repopulates on next call.
  3. Clear PPIO_MODEL_PREF and re-select the model in the UI.
  4. Verify the key's plan includes the model on the PPIO dashboard.

Example fix

// before
const llm = new PPIOLLM(embedder, "deepseek/deepseek-r1"); // not in synced set
await llm.getChatCompletion(messages, { temperature: 0.7 });

// after
const known = await llm.isValidChatCompletionModel("deepseek/deepseek-r1");
const model = known ? "deepseek/deepseek-r1" : "qwen/qwen2.5-32b-instruct";
const llm2 = new PPIOLLM(embedder, model);
await llm2.getChatCompletion(messages, { temperature: 0.7 });
Defensive patterns

Strategy: validation

Validate before calling

// PPIO's check is async because it syncs the catalog first
const valid = await llm.isValidChatCompletionModel(llm.model);
if (!valid) {
  const fallback = "qwen/qwen2.5-32b-instruct";
  llm = new PPIOLLM(embedder, fallback);
  if (!(await llm.isValidChatCompletionModel(llm.model))) {
    throw new Error(`PPIO has no usable model for this key (sync may have failed)`);
  }
}

Type guard

async function isKnownPpioModel(llm, id) {
  return typeof id === "string" && (await llm.isValidChatCompletionModel(id));
}

Try / catch

try {
  return await llm.getChatCompletion(messages, opts);
} catch (e) {
  if (/not valid for chat completion/i.test(e.message)) {
    llm.model = "qwen/qwen2.5-32b-instruct";
    return llm.getChatCompletion(messages, opts);
  }
  throw e;
}

Prevention

When it happens

Trigger: this.model is not returned by PPIO's models endpoint: a typo, a model the account cannot access, a model id that was retired, or #syncModels failed silently and the cache is empty/stale.

Common situations: PPIO_MODEL_PREF points at a model removed from the catalog; first run when storage/models/ppio cache is empty and the sync fetch returned an unexpected payload; passing a text model id to a vision-only endpoint name; the account tier does not include the requested model.

Related errors


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