{"record":{"id":"6df627ba6f803d56","repo":"Hmbown/CodeWhale","slug":"runtime-model-catalog-cursor-repeated","errorCode":null,"errorMessage":"Runtime model catalog cursor repeated","messagePattern":"Runtime model catalog cursor repeated","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/app-server/src/lib.rs","lineNumber":1689,"sourceCode":"                    .get(\"models\")\n                    .and_then(Value::as_array)\n                    .and_then(|models| {\n                        models\n                            .iter()\n                            .find(|entry| entry.get(\"id\").and_then(Value::as_str) == Some(model))\n                    })\n            {\n                if entry.get(\"output_token_limit\").and_then(Value::as_str) == Some(\"supported\") {\n                    return Ok(());\n                }\n                bail!(\"The selected Runtime model does not support maxOutputTokens\");\n            }\n            let next = catalog\n                .get(\"nextCursor\")\n                .and_then(Value::as_str)\n                .context(\"Output-limit support is unknown for the selected Runtime model\")?;\n            if !seen.insert(next.to_string()) {\n                bail!(\"Runtime model catalog cursor repeated\");\n            }\n            cursor = Some(next.to_string());\n        }\n    }\n\n    /// Resolve `stdio_thread_id` to a runtime thread, minting one only when\n    /// `thread_map` has no entry. The map lives on [`AppState`] and outlives\n    /// this bridge, so a thread created under a previous child keeps its id\n    /// here as long as the store it was persisted to is shared (#6246).\n    async fn ensure_runtime_thread(\n        &mut self,\n        thread_map: &mut HashMap<String, String>,\n        stdio_thread_id: &str,\n        hint: Option<RuntimeThreadHint>,\n    ) -> Result<String> {\n        if let Some(runtime_thread_id) = thread_map.get(stdio_thread_id) {\n            return Ok(runtime_thread_id.clone());\n        }","sourceCodeStart":1671,"sourceCodeEnd":1707,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/app-server/src/lib.rs#L1671-L1707","documentation":"The catalog pagination loop guards against a Runtime that keeps returning the same `nextCursor`, which would loop forever. Each cursor is inserted into a `seen` set; a repeat aborts with this error. It indicates a Runtime API pagination bug or a malformed catalog response.","triggerScenarios":"During output-token capability resolution, two successive catalog pages return an identical `nextCursor` value that was already visited.","commonSituations":"Buggy or mismatched Runtime version whose /v1/providers/{id}/models endpoint returns a stale cursor; a proxy caching catalog pages.","solutions":["Upgrade or restart the Runtime — this is a runtime-side pagination defect.","Check for caching proxies in front of the Runtime API returning stale pages.","Pin the model explicitly (avoiding catalog paging) if the endpoint is known-good for single-page results."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// treat a repeated cursor as a runtime bug and degrade gracefully\nmatch resolve_output_support(model).await {\n    Err(e) if e.to_string().contains(\"cursor repeated\") => {\n        log::warn!(\"runtime catalog pagination broken; skipping capability check\");\n        Ok(()) // proceed without the capability guarantee, or disable maxOutputTokens\n    }\n    other => other,\n}","preventionTips":["Keep app-server and Runtime versions aligned; pagination bugs are version-skew symptoms.","Bypass caching proxies for runtime catalog endpoints.","Bound all pagination loops with a page cap in client-side wrappers."],"tags":["pagination","api","runtime","infinite-loop"],"backgroundTag":"unexpected-response-shape","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}