Hmbown/CodeWhale · warning
The provider catalog changed; restart loading its models.
Error message
The provider catalog changed; restart loading its models.
What it means
Thrown when a subsequent page of the provider catalog reports a different `total` than earlier pages. The loader captures the total from the first page and requires it to stay constant across all pages; a drift means the catalog mutated mid-pagination and the accumulated entries would be inconsistent.
Solutions
- Close and reopen the new-thread dialog (or reload) to restart pagination with a fresh expectedTotal
- Retry after the provider catalog finishes syncing
- Ensure a single Runtime instance serves the session (no load balancing across nodes with divergent catalogs)
- Avoid changing provider configuration while the model list is loading
Example fix
// before: swallowing stale totals and appending anyway
entries.push(...pageEntries);
// after: restart the load when the catalog changed
if (expectedTotal !== undefined && page.total !== expectedTotal) {
await openNewThreadDialog(); // re-triggers collectProviderModelPages from scratch
return;
} Defensive patterns
Strategy: retry
Validate before calling
if (expectedTotal !== undefined && page.total !== expectedTotal) scheduleReload();
Type guard
const totalsAgree = (page, expected) => expected === undefined || page?.total === expected;
Try / catch
try { await loadModels(provider); } catch (e) { if (String(e.message).includes('catalog changed')) await reloadDialog(); } Prevention
- Avoid mutating provider configuration while the dialog is open
- Serve the session from a single Runtime instance
- Retry loads after provider sync jobs finish
- Treat this error as restartable, not fatal
When it happens
Trigger: Calling collectProviderModelPages while the provider's model list changes server-side between page fetches, so page 2's `total` differs from page 1's.
Common situations: Provider syncs a model list (models added/removed) while the user has the new-thread dialog open; load balancer routing page requests to different Runtime instances with different catalogs; a hot reload or config change updating the provider config mid-load.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- The provider catalog exceeds
- The Runtime returned a cursor beyond its provider model…
- The Runtime returned an incomplete provider model catalog.
- The Runtime returned an invalid provider model page.
- A provider and page loader are required.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ce95efabbbd9a93c.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_web/app.mjs:677
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);
const nextCursor = typeof response?.nextCursor === "string"
? response.nextCursor.trim()
: "";
if (!nextCursor) {
if (entries.length !== expectedTotal) {
throw new Error("The Runtime returned an incomplete provider model catalog.");
}
return entries;
}
if (pageEntries.length === 0 || seenCursors.has(nextCursor)) {View on GitHub (pinned to 73e0f67d83)