can1357/oh-my-pi · error

Retry fallback model not found: ${selector.raw}

Error message

Retry fallback model not found: ${selector.raw}

What it means

TurnRecovery's retry-fallback path resolves a model selector string (e.g. 'provider/model-id') via resolveModelOverride and the model registry, then throws if neither produces a candidate model. This means the selector the caller asked to fall back to does not match any model known to the registry (including any override/pinning logic). It is thrown before any API call is attempted.

Source

Thrown at packages/coding-agent/src/session/turn-recovery.ts:1705

		const onAbort = () => aborted.resolve(false);
		signal.addEventListener("abort", onAbort, { once: true });
		try {
			return await Promise.race([confirmer(confirmation, signal), aborted.promise]);
		} finally {
			signal.removeEventListener("abort", onAbort);
		}
	}

	async applyRetryFallbackCandidate(
		role: string,
		selector: RetryFallbackSelector,
		currentSelector: string,
		options?: { pinFallback?: boolean; apiKey?: string; signal?: AbortSignal },
	): Promise<boolean> {
		const resolved = resolveModelOverride([selector.raw], this.#host.modelRegistry, this.#host.settings);
		const candidate = resolved.model ?? this.#host.modelRegistry.find(selector.provider, selector.id);
		if (!candidate) {
			throw new Error(`Retry fallback model not found: ${selector.raw}`);
		}
		const apiKey =
			options?.apiKey ??
			(await this.#host.modelRegistry.getApiKey(candidate, this.#host.sessionId(), { signal: options?.signal }));
		if (!apiKey) {
			throw new Error(`No API key for retry fallback ${selector.raw}`);
		}
		if (options?.signal?.aborted) return false;

		// Capture the configured selector (auto-aware) so a fallback chain preserves
		// `auto` instead of collapsing it to the level it resolved to this turn.
		const currentThinkingLevel = this.#host.configuredThinkingLevel();
		const requestedThinkingLevel = selector.thinkingLevel ?? currentThinkingLevel;
		// A fallback selector's explicit level (or the carried level after the
		// replacement model's floor clamp) must never exceed the session's
		// per-spawn effort ceiling.
		const nextThinkingLevel =
			requestedThinkingLevel === AUTO_THINKING

View on GitHub (pinned to 9690622007)

Solutions

  1. Verify the selector string matches an available model (run the same resolveModelOverride/registry lookup interactively or list registry models).
  2. Correct the fallback selector in the session/config that supplied it (typos, old ids).
  3. Ensure the provider's models are registered/loaded before the retry path runs (check registry.getAvailable()).
  4. If resolveModelOverride returns nothing because the override points at a removed model, clear the stale override.

Example fix

// before
await recovery.retryWithFallback({ raw: "anthropic/claude-3-5-sonet" });
// after
await recovery.retryWithFallback({ raw: "anthropic/claude-3-5-sonnet" }); // id that exists in the registry
Defensive patterns

Strategy: validation

Validate before calling

const resolved = resolveModelOverride([selector.raw], registry, settings);
const candidate = resolved.model ?? registry.find(selector.provider, selector.id);
if (!candidate) throw new Error(`Fallback model unavailable: ${selector.raw}`);

Type guard

function isKnownModel(registry: ModelRegistry, provider: string, id: string): boolean {
  return registry.find(provider, id) !== undefined;
}

Try / catch

try {
  await recovery.retryWithFallback(selector, opts);
} catch (err) {
  if (err instanceof Error && err.message.startsWith("Retry fallback model not found")) {
    // fall back to the primary model or surface a config error to the user
  } else throw err;
}

Prevention

When it happens

Trigger: Calling the TurnRecovery retry-fallback method with options.pinFallback or a selector whose raw string does not resolve: misspelled model id, model removed/renamed in the registry, or a provider whose models were not loaded/available.

Common situations: A saved session or config references a model id from an older version of the catalog; user hand-edits a fallback selector; provider plugin not registered so its models are absent from the registry; typo in provider name.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/199cb48ba0994c0f. Report an issue: GitHub.