{"record":{"id":"dd12ab8edfca794c","repo":"can1357/oh-my-pi","slug":"models-catalog-fetch-failed-response-status","errorCode":null,"errorMessage":"models catalog fetch failed: ${response.status}","messagePattern":"models catalog fetch failed: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/catalog/src/provider-models/openai-compat.ts","lineNumber":224,"sourceCode":"\nasync function fetchCatalogPayload(\n\tfetchImpl: FetchImpl,\n\tsession: CatalogSession,\n\tsignal?: AbortSignal,\n): Promise<unknown> {\n\tconst headers: Record<string, string> = {\n\t\tAccept: \"application/zstd, application/json\",\n\t\t\"User-Agent\": CATALOG_USER_AGENT,\n\t};\n\tif (session.hasPayload && session.etag) {\n\t\theaders[\"If-None-Match\"] = session.etag;\n\t}\n\tconst response = await fetchImpl(MODELS_DEV_URL, { method: \"GET\", headers, signal });\n\tif (response.status === 304 && session.hasPayload) {\n\t\treturn session.payload;\n\t}\n\tif (!response.ok) {\n\t\tthrow new Error(`models catalog fetch failed: ${response.status}`);\n\t}\n\tconst bytes = new Uint8Array(await response.arrayBuffer());\n\tconst isZstd = bytes.length >= 4 && new DataView(bytes.buffer, bytes.byteOffset).getUint32(0, true) === ZSTD_MAGIC;\n\tconst text = new TextDecoder().decode(isZstd ? await Bun.zstdDecompress(bytes) : bytes);\n\tconst payload: unknown = JSON.parse(text);\n\tsession.payload = payload;\n\tsession.etag = response.headers.get(\"etag\");\n\tsession.hasPayload = true;\n\treturn payload;\n}\n\nfunction mapAnthropicModelsDev(payload: unknown, baseUrl: string): ModelSpec<\"anthropic-messages\">[] {\n\tif (!isRecord(payload)) {\n\t\treturn [];\n\t}\n\tconst anthropicPayload = payload.anthropic;\n\tif (!isRecord(anthropicPayload)) {\n\t\treturn [];","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/catalog/src/provider-models/openai-compat.ts#L206-L242","documentation":"fetchCatalogPayload downloads the models.dev catalog (optionally zstd-compressed) with revalidation via HTTP caching. It throws when the server responds with a non-ok status and there is no cached 304 payload to fall back to.","triggerScenarios":"GET MODELS_DEV_URL returns 4xx/5xx (rate limit 429, 5xx outage, blocked by proxy) while session.hasPayload is false (first run or cache cleared).","commonSituations":"Offline or behind a corporate proxy, models.dev rate-limiting, DNS failures surfaced as odd statuses, transient CDN errors during model discovery.","solutions":["Check network/proxy access to https://models.dev and retry","Clear/repopulate the cache so a 304 fallback payload exists","Check for rate limiting (429) and back off","Pin or vendor a catalog payload if you need offline builds"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  payload = await fetchCatalogPayload();\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith(\"models catalog fetch failed\")) {\n    logger.warn(\"models.dev unreachable; using last cached catalog\", { cause: err });\n    return cachedPayload;\n  }\n  throw err;\n}","preventionTips":["Ensure outbound access to models.dev (allowlist proxies/firewalls)","Keep a warm cache so a 304 fallback exists on first failure","Back off on 429 rate-limit responses"],"tags":["network","http","catalog"],"backgroundTag":"http-request-failed","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}