{"record":{"id":"ef2fde78306bbf1c","repo":"different-ai/openwork","slug":"provider-details-could-not-be-parsed","errorCode":null,"errorMessage":"Provider details could not be parsed.","messagePattern":"Provider details could not be parsed\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/llm-provider-data.tsx","lineNumber":493,"sourceCode":"\nexport async function requestLlmProviderCatalogDetail(orgId: string, providerId: string) {\n  const { response, payload } = await requestJson(\n    `/v1/llm-provider-catalog/${encodeURIComponent(providerId)}`,\n    { method: \"GET\" },\n    20000,\n  );\n\n  if (!response.ok) {\n    throw new Error(getErrorMessage(payload, `Failed to load provider details (${response.status}).`));\n  }\n\n  if (!isRecord(payload) || !payload.provider) {\n    throw new Error(\"Provider details were missing from the response.\");\n  }\n\n  const detail = asCatalogProviderDetail(payload.provider);\n  if (!detail) {\n    throw new Error(\"Provider details could not be parsed.\");\n  }\n\n  return detail;\n}\n\nexport function useOrgLlmProviders(\n  orgId: string | null,\n  options: { scope?: \"usable\" | \"manageable\" } = {},\n) {\n  const [llmProviders, setLlmProviders] = useState<DenLlmProvider[]>([]);\n  const [busy, setBusy] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n  const scope = options.scope ?? \"manageable\";\n\n  async function loadProviders() {\n    if (!orgId) {\n      setLlmProviders([]);\n      setError(\"Organization not found.\");","sourceCodeStart":475,"sourceCodeEnd":511,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/llm-provider-data.tsx#L475-L511","documentation":"After locating payload.provider, the code runs it through asCatalogProviderDetail; if that validator returns null the provider object does not match the expected detail schema and this error is thrown. It ensures the editor screen never renders an invalid provider detail object.","triggerScenarios":"payload.provider exists but fails asCatalogProviderDetail validation — missing required fields (e.g. models list, pricing fields), wrong field types, or a newly added catalog provider shape the validator does not recognize.","commonSituations":"models.dev upstream added/renamed provider metadata fields and the server passes them through; a new provider entry in the catalog doesn't satisfy the frontend's expected schema; partial data cached server-side.","solutions":["Log payload.provider and diff its keys against what asCatalogProviderDetail requires.","Extend asCatalogProviderDetail to accept the new/optional fields.","Fix the server-side normalization so catalog details are always complete before responding.","If caused by a specific provider, exclude or repair that provider's upstream data."],"exampleFix":"// before\nfunction asCatalogProviderDetail(v: unknown) {\n  if (!isRecord(v) || typeof v.models !== \"object\") return null;\n  ...\n}\n// after (tolerate missing models as empty list)\nfunction asCatalogProviderDetail(v: unknown) {\n  if (!isRecord(v)) return null;\n  const models = Array.isArray(v.models) ? v.models : [];\n  ...\n}","handlingStrategy":"type-guard","validationCode":"function validateProviderDetailShape(v: unknown): string[] {\n  const problems: string[] = [];\n  if (typeof v !== \"object\" || v === null) return [\"not an object\"];\n  const r = v as Record<string, unknown>;\n  if (typeof r.id !== \"string\") problems.push(\"id missing\");\n  if (typeof r.name !== \"string\") problems.push(\"name missing\");\n  if (!Array.isArray(r.models)) problems.push(\"models not an array\");\n  return problems;\n}","typeGuard":"function isCatalogProviderDetail(v: unknown): v is CatalogProviderDetail {\n  if (typeof v !== \"object\" || v === null) return false;\n  const r = v as Record<string, unknown>;\n  return typeof r.id === \"string\" && typeof r.name === \"string\" && Array.isArray(r.models);\n}","tryCatchPattern":"try {\n  const detail = await requestLlmProviderCatalogDetail(providerId);\n} catch (err) {\n  if (err instanceof Error && err.message === \"Provider details could not be parsed.\") {\n    console.error(\"Provider detail failed schema validation — likely upstream models.dev change\");\n  } else throw err;\n}","preventionTips":["Normalize provider details server-side to a fixed schema before responding.","Make asCatalogProviderDetail tolerant of optional new fields with defaults.","Add fixtures for every catalog provider through the validator in CI.","Watch upstream (models.dev) changelogs for metadata shape changes."],"tags":["schema-validation","api-contract","llm-provider-catalog","den-web"],"backgroundTag":"schema-validation-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}