Hmbown/CodeWhale · error

The Runtime returned a model page for a different provider.

Error message

The Runtime returned a model page for a different provider.

What it means

Each fetched page of a provider's model catalog must echo the provider id it was requested for. When response.provider does not match the requested provider, the runtime treats the catalog as corrupted/cross-wired (cursors and totals would be meaningless across providers) and throws rather than silently merging foreign models.

Solutions

  1. Log the requested provider and response.provider to see the mismatch (casing, encoding, or a different id entirely).
  2. Bypass any proxy/cache and call the Runtime directly to rule out stale cached pages.
  3. Fix or report the server-side provider-id normalization so the response echoes the exact requested id.

Example fix

// before
const page = await fetchPage(`/v1/providers/${id}/models?...`);
// after
const page = await fetchPage(`/v1/providers/${encodeURIComponent(id)}/models?...`);
if (String(page?.provider || '') !== id) throw new Error('provider mismatch: ' + page?.provider);
Defensive patterns

Strategy: try-catch

Validate before calling

const page = await fetchPage(url);
if (String(page?.provider || '') !== providerId) {
  throw new Error('page provider mismatch');
}

Type guard

function isPageForProvider(response, providerId) {
  return String(response?.provider || '') === providerId &&
         Array.isArray(response?.models);
}

Try / catch

try {
  const models = await collectProviderModelPages(providerId, fetchPage);
} catch (e) {
  if (String(e.message).includes('different provider')) {
    invalidateCatalogCache();
    // refetch directly from the Runtime
  } else throw e;
}

Prevention

When it happens

Trigger: The Runtime endpoint /v1/providers/<id>/models returns a body whose `provider` field is absent, different, or differently-cased/encoded than the requested id; a proxy/cache returns a cached page for another provider.

Common situations: Provider id casing/URL-encoding mismatch between request and response; misbehaving intermediate proxy serving stale pages; server bug mapping provider ids to catalogs.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/041321e420895c5b. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_web/app.mjs:667

 */
export async function collectProviderModelPages(providerId, fetchPage) {
  const provider = String(providerId || "").trim();
  if (!provider || typeof fetchPage !== "function") {
    throw new Error("A provider and page loader are required.");
  }

  const entries = [];
  const seenCursors = new Set();
  let expectedTotal;
  let cursor = "";
  for (let page = 0; page < MAX_PROVIDER_MODEL_PAGES; page += 1) {
    const query = new URLSearchParams({ limit: String(PROVIDER_MODELS_PAGE_SIZE) });
    if (cursor) query.set("cursor", cursor);
    const response = await fetchPage(
      `/v1/providers/${encodeURIComponent(provider)}/models?${query.toString()}`,
    );
    if (String(response?.provider || "") !== provider) {
      throw new Error("The Runtime returned a model page for a different provider.");
    }
    if (!Array.isArray(response?.models)
      || response.models.length > PROVIDER_MODELS_PAGE_SIZE
      || !Number.isSafeInteger(response.total)
      || response.total < 0
      || response.total > MAX_PROVIDER_MODELS) {
      throw new Error("The Runtime returned an invalid provider model page.");
    }
    if (expectedTotal !== undefined && expectedTotal !== response.total) {
      throw new Error("The provider catalog changed; restart loading its models.");
    }
    expectedTotal = response.total;
    const pageEntries = response.models;
    if (entries.length + pageEntries.length > MAX_PROVIDER_MODELS) {
      throw new Error(`The provider catalog exceeds ${MAX_PROVIDER_MODELS} models.`);
    }
    entries.push(...pageEntries);

View on GitHub (pinned to 73e0f67d83)