{"record":{"id":"2fd779fa30c2c6c7","repo":"can1357/oh-my-pi","slug":"clinepass-model-catalog-response-is-missing-clinep","errorCode":null,"errorMessage":"ClinePass model catalog response is missing clinePass","messagePattern":"ClinePass model catalog response is missing clinePass","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/catalog/src/provider-models/openai-compat.ts","lineNumber":2690,"sourceCode":"\nasync function fetchClinePassModels(\n\tfetchImpl: FetchImpl,\n\treferences: ReadonlyMap<string, ModelSpec<\"openai-completions\">>,\n): Promise<ModelSpec<\"openai-completions\">[]> {\n\t// The roster is authoritative for ids; the live reference catalog is a pure\n\t// enrichment tier fetched alongside and tolerated away (offline → bundle).\n\tconst [response, liveCatalog] = await Promise.all([\n\t\twithCatalogDiscoveryTimeout(5_000, signal =>\n\t\t\tfetchImpl(CLINEPASS_MODELS_URL, { signal, headers: clinePassClientHeaders() }),\n\t\t),\n\t\tfetchClinePassLiveCatalog(fetchImpl),\n\t]);\n\tif (!response.ok) {\n\t\tthrow new Error(`Failed to fetch ClinePass models: HTTP ${response.status}`);\n\t}\n\tconst payload: unknown = await response.json();\n\tif (!isRecord(payload) || !Array.isArray(payload.clinePass)) {\n\t\tthrow new Error(\"ClinePass model catalog response is missing clinePass\");\n\t}\n\n\tconst models = new Map<string, ModelSpec<\"openai-completions\">>();\n\tfor (const entry of payload.clinePass) {\n\t\tif (!isRecord(entry) || typeof entry.id !== \"string\") {\n\t\t\tcontinue;\n\t\t}\n\t\tconst wireId = entry.id.trim();\n\t\tif (!wireId.startsWith(\"cline-pass/\")) {\n\t\t\tcontinue;\n\t\t}\n\t\tconst id = toClinePassPublicModelId(wireId).trim();\n\t\tif (!id) {\n\t\t\tcontinue;\n\t\t}\n\t\tmodels.set(id, buildClinePassSubscriptionModel(id, references, liveCatalog));\n\t}\n\tif (models.size === 0) {","sourceCodeStart":2672,"sourceCodeEnd":2708,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/catalog/src/provider-models/openai-compat.ts#L2672-L2708","documentation":"After a successful (ok) fetch, the ClinePass mapper validates the JSON payload shape: it must be a record containing a `clinePass` array. This throw means the server returned 200 but the body is not the expected catalog shape, so parsing is aborted rather than producing zero models.","triggerScenarios":"ClinePass /models endpoint returns 200 with a JSON body lacking `clinePass` or where `clinePass` is not an array (API contract change, HTML login page served with 200, empty placeholder).","commonSituations":"ClinePass API schema version drift, hitting an auth/portal URL that returns 200 HTML, an edge proxy serving a cached empty response.","solutions":["Log/inspect the actual response body to see what changed","Update the catalog package to match the current ClinePass API schema","Verify the request is authenticated so the real catalog (not a portal page) is returned","Bypass proxies/caches to rule out a stale cached 200 response"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const res = await fetch(CLINEPASS_MODELS_URL, { headers: clinePassClientHeaders() });\nconst payload = await res.json();\nif (!(payload && typeof payload === \"object\") || !Array.isArray(payload.clinePass)) {\n  throw new Error(\"Unexpected ClinePass response shape\");\n}\n","typeGuard":"function isClinePassCatalog(payload: unknown): payload is { clinePass: { id: string }[] } {\n  return typeof payload === \"object\" && payload !== null\n    && Array.isArray((payload as { clinePass?: unknown }).clinePass);\n}","tryCatchPattern":"try {\n  models = await fetchClinePassModels();\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"missing clinePass\")) {\n    logger.warn(\"ClinePass schema changed; falling back to cached catalog\", { cause: err });\n    return cachedModels;\n  }\n  throw err;\n}","preventionTips":["Verify authenticated requests return the real catalog, not an HTML portal page","Validate the payload shape before consuming it in your own code","Track ClinePass API schema updates and keep the catalog package current"],"tags":["schema","validation","discovery"],"backgroundTag":"schema-validation-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}