Hmbown/CodeWhale · error
The Runtime returned a non-progressing model cursor.
Error message
The Runtime returned a non-progressing model cursor.
What it means
Thrown when a page yields an empty entries array while still returning a cursor, or when the returned cursor was already visited. Pagination must strictly progress; either condition means an infinite loop would occur, so the loader aborts.
Solutions
- Restart `codewhale web` with a current Runtime build (fixed cursor logic)
- Bypass intermediate caches so each cursor request reaches the Runtime
- Verify the provider adapter honors the cursor/offset parameter
- Reload the dialog to restart pagination; if it recurs, file a Runtime bug with the cursor values
Example fix
// before: looping on the same cursor until the cap trips
while (nextCursor) { page = await fetch('?cursor=' + nextCursor); }
// after: detect non-progress like the loader does
if (!page.models.length || visited.has(page.nextCursor)) throw new Error('non-progressing model cursor'); Defensive patterns
Strategy: validation
Validate before calling
const visited = new Set(); if (visited.has(page.nextCursor) || !page.models.length) abortLoad();
Type guard
const cursorProgresses = (page, seen) => Array.isArray(page?.models) && page.models.length > 0 && !seen.has(page?.nextCursor);
Try / catch
try { models = await loadCatalog(); } catch (e) { if (String(e.message).includes('non-progressing')) reportRuntimeBug(e); } Prevention
- Keep Runtime cursor implementations advancing monotonically
- Bypass caches for cursor-paginated requests
- Test provider adapters honor cursor parameters
- Abort pagination on the first repeated cursor instead of looping
When it happens
Trigger: Runtime returns {models: [], nextCursor: "x"} or re-issues a cursor previously passed in seenCursors — typically a cursor implementation that doesn't advance (e.g. cursor encoding the same offset repeatedly).
Common situations: A Runtime build with a broken cursor codec; a provider adapter that ignores the cursor parameter and always returns the same page; caching middleware replaying an identical response for successive cursor requests.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- MCP repeated a pagination cursor
- repeated pagination cursor; aborting
- Runtime model catalog cursor repeated
- The Runtime returned a cursor beyond its provider model…
- A provider and page loader are required.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/ef57bf60389092f2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_web/app.mjs:696
}
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)) {
throw new Error("The Runtime returned a non-progressing model cursor.");
}
if (entries.length >= expectedTotal) {
throw new Error("The Runtime returned a cursor beyond its provider model catalog.");
}
seenCursors.add(nextCursor);
cursor = nextCursor;
}
throw new Error(`The provider catalog exceeds ${MAX_PROVIDER_MODELS} models.`);
}
function startBrowserClient() {
const dom = {
shell: document.querySelector("#app-shell"),
rail: document.querySelector("#thread-rail"),
railOpen: document.querySelector("#rail-open"),
railClose: document.querySelector("#rail-close"),
railScrim: document.querySelector("#rail-scrim"),
search: document.querySelector("#thread-search"),View on GitHub (pinned to 73e0f67d83)