continuedev/continue · error · Error

No model selected

Error message

No model selected

What it means

streamDiffLines resolves the model by title across edit/apply/chat roles with a fallback to the selected chat model; if none match and no chat default exists, llm is undefined and it throws 'No model selected'.

Source

Thrown at core/core.ts:757

    on("streamDiffLines", async (msg) => {
      const { config } = await this.configHandler.loadConfig();
      if (!config) {
        throw new Error("Failed to load config");
      }

      const { data } = msg;

      // Title can be an edit, chat, or apply model
      // Fall back to chat
      const llm =
        config.modelsByRole.edit.find((m) => m.title === data.modelTitle) ??
        config.modelsByRole.apply.find((m) => m.title === data.modelTitle) ??
        config.modelsByRole.chat.find((m) => m.title === data.modelTitle) ??
        config.selectedModelByRole.chat;

      if (!llm) {
        throw new Error("No model selected");
      }

      const abortManager = ApplyAbortManager.getInstance();
      const abortController = abortManager.get(
        data.fileUri ?? "current-file-stream",
      ); // not super important since currently cancelling apply will cancel all streams it's one file at a time

      return streamDiffLines(
        data,
        llm,
        abortController,
        undefined,
        data.includeRulesInSystemMessage ? config.rules : undefined,
      );
    });

    on("getDiffLines", (msg) => {
      return myersDiff(msg.data.oldContent, msg.data.newContent);

View on GitHub (pinned to 5522c6f44c)

Solutions

  1. Re-select a valid model in the apply/edit UI so a fresh title is sent
  2. Ensure the referenced modelTitle exists in config.modelsByRole
  3. Set a default chat model as fallback

Example fix

// before
send("streamDiffLines", { data: { modelTitle: "old-model" } });
// after
const ok = config.modelsByRole.chat.some(m => m.title === title);
send("streamDiffLines", { data: { modelTitle: ok ? title : undefined } });
Defensive patterns

Strategy: type-guard

Validate before calling

const titles = new Set([...config.modelsByRole.edit, ...config.modelsByRole.apply, ...config.modelsByRole.chat].map(m => m.title));
if (data.modelTitle && !titles.has(data.modelTitle)) delete data.modelTitle;

Type guard

const modelExists = (t: string, c: Config) =>
  c.modelsByRole.edit.concat(c.modelsByRole.apply, c.modelsByRole.chat).some(m => m.title === t);

Try / catch

catch (e) { if (e.message === 'No model selected') { retryWithDefaultChatModel(data); } }

Prevention

When it happens

Trigger: Passing a modelTitle in the streamDiffLines payload that matches no configured model, while also having no default chat model.

Common situations: Stale model title from a saved session after the model was renamed/removed; config pruned; UI sends title of a deleted model.

Related errors


AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27). Data as JSON: /api/errors/13ea1bd662057a18. Report an issue: GitHub.