different-ai/openwork · error · Error

Selected model is unavailable. Choose another model before s

Error message

Selected model is unavailable. Choose another model before sending.

What it means

Before sending a message, the send path validates the exact model identity this conversation will submit (session-scoped selection, falling back to the user's default model) with resolveModelAvailability(). If that model's status is 'unavailable' — e.g. the provider is disconnected, the model was removed, or the API key is missing — the send is rejected with this error instead of failing server-side.

Source

Thrown at apps/app/src/react-app/shell/session-route.tsx:1275

          openSettings: handleOpenSettings,
        });
      },
      onSendDraft: async (draft: ComposerDraft, sessionId: string): Promise<CloudMcpSubmissionResult> => {
        const targetSessionId = sessionId.trim() || selectedSessionId;
        if (!targetSessionId) return { outcome: "cancelled", reason: "context_changed" };
        const text = (draft.resolvedText ?? draft.text).trim();
        if (!text && draft.attachments.length === 0) {
          return { outcome: "cancelled", reason: "context_changed" };
        }
        // Per-conversation model memory: a session that picked its own model
        // sends with it (and its variant) instead of the global default.
        const sessionModelSelection = getSessionModelSelection(targetSessionId);
        const sendModel = sessionModelSelection?.model ?? local.prefs.defaultModel;
        const sendVariant = sessionModelSelection ? sessionModelSelection.variant : modelVariantValue;
        // Send-time validation targets the exact provider/model identity this
        // conversation displays and will submit — not the global default.
        if (resolveModelAvailability(sendModel ?? null).status === "unavailable") {
          throw new Error("Selected model is unavailable. Choose another model before sending.");
        }

        return submitWithCloudMcpReadiness({
          // Temporarily bypass the pre-send Cloud MCP gate: it blocks every
          // message, including tasks that do not use connected services.
          skipGate: true,
          send: async () => {
            await sendWithRevertRollback({
              revertMessageId: draft.revertMessageId,
              abort: () => abortSessionSafe(opencodeClient, targetSessionId, selectedWorkspaceRoot || undefined, {
                source: "session.edit_resend.before_revert",
                initiator: "user",
                reason: "abort active run before replacing a reverted message",
              }),
              revert: async (messageId) => {
                const reverted = await revertSession(opencodeClient, targetSessionId, messageId);
                applySessionRevert(selectedWorkspaceId, reverted);
              },

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Open the model picker for the conversation and choose an available model, then resend
  2. Reconnect or re-authenticate the provider that owns the model (add/fix its API key in Settings → Models/Providers)
  3. Clear the stale session model selection so it falls back to a valid defaultModel
  4. Update the app/provider catalog if the model id changed upstream

Example fix

// before
useSessionModelStore.getState().setModel(sessionId, "anthropic/claude-2.1", null) // stale id
// after
useSessionModelStore.getState().setModel(sessionId, resolveFirstAvailableModel(), null)
Defensive patterns

Strategy: validation

Validate before calling

const availability = resolveModelAvailability(sendModel ?? null);
if (availability.status === "unavailable") {
  notify(`Model ${sendModel} is unavailable; pick another.`);
  return;
}
await send();

Type guard

const isModelAvailable = (m: string | null | undefined): m is string =>
  !!m && resolveModelAvailability(m).status !== "unavailable";

Try / catch

try {
  await send();
} catch (e) {
  if (String(e.message).startsWith("Selected model is unavailable")) {
    openModelPicker(targetSessionId);
  }
}

Prevention

When it happens

Trigger: Calling the send/submit handler when resolveModelAvailability(sendModel).status === 'unavailable': session model selection or defaultModel points to a provider/model that is disconnected, unauthenticated, or no longer in the model list.

Common situations: A provider API key was revoked or removed from settings; models.dev/provider catalog changed and an old model id persists in the session store; cloud inference was disabled; user switched from a local to a remote workspace whose endpoint lacks that model.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/379c4d4e52a29e1e. Report an issue: GitHub.