{"record":{"id":"0f16739e0ba26647","repo":"different-ai/openwork","slug":"inference-settings-response-was-incomplete","errorCode":null,"errorMessage":"Inference settings response was incomplete.","messagePattern":"Inference settings response was incomplete\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/inference-screen.tsx","lineNumber":326,"sourceCode":"  const isSelfHosted = runtimeConfigLoaded && runtimeConfig.orgMode === \"single_org\";\n  const activeOrgSlug = activeOrg?.slug ?? null;\n\n  useEffect(() => {\n    if (!isSelfHosted) return;\n    router.replace(getCustomLlmProvidersRoute(activeOrgSlug));\n  }, [isSelfHosted, activeOrgSlug, router]);\n\n  async function loadStatus() {\n    setLoading(true);\n    setError(null);\n    try {\n      const { response, payload } = await requestJson(\"/v1/inference\", { method: \"GET\" }, 12000);\n      if (!response.ok) {\n        throw new Error(getErrorMessage(payload, `Failed to load inference settings (${response.status}).`));\n      }\n      const parsed = parseInferencePayload(payload);\n      if (!parsed) {\n        throw new Error(\"Inference settings response was incomplete.\");\n      }\n      setStatus(parsed);\n    } catch (loadError) {\n      setError(loadError instanceof Error ? loadError.message : \"Failed to load inference settings.\");\n    } finally {\n      setLoading(false);\n    }\n  }\n\n  useEffect(() => {\n    void loadStatus();\n  }, [orgContext?.organization.id]);\n\n  // Subscribe at the point of value: start the Stripe checkout right here\n  // instead of bouncing the user to the billing page. Billing stays the\n  // status/portal view.\n  async function startSubscribeCheckout() {\n    if (!canManageModels) {","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/inference-screen.tsx#L308-L344","documentation":"loadStatus fetches GET /v1/inference and runs parseInferencePayload on the JSON body. When the response is HTTP 200 but the payload is missing or has malformed fields required to build an InferenceStatus, the parser returns null and this error is thrown. It indicates a server-side contract violation rather than a network or auth failure.","triggerScenarios":"GET /v1/inference returns 200 with a body that parseInferencePayload rejects: missing required fields (e.g. enabled/subscription/model data), an HTML or empty body instead of JSON, or an API version that changed the response shape.","commonSituations":"Server deployed at a different version than the dashboard frontend (API contract drift); a proxy/gateway returning an HTML error page with 200; self-hosted server with an older /v1/inference implementation.","solutions":["Check the server version serving /v1/inference and upgrade so it matches the dashboard's expected InferenceStatus contract.","Log the raw payload from /v1/inference (curl with auth cookie) to see which required field is missing or null.","Bypass or fix any proxy that could return non-JSON 200 bodies for this endpoint.","Retry after a transient deploy; if persistent, file a backend bug with the raw response."],"exampleFix":"// before\nconst parsed = parseInferencePayload(payload);\nif (!parsed) throw new Error(\"Inference settings response was incomplete.\");\n// after\nconst parsed = parseInferencePayload(payload);\nif (!parsed) throw new Error(`Inference settings response was incomplete: ${JSON.stringify(payload).slice(0, 200)}`);","handlingStrategy":"type-guard","validationCode":"const res = await fetch(\"/v1/inference\", { credentials: \"include\" });\nconst body = await res.json();\nconst parseable = typeof body === \"object\" && body !== null && \"enabled\" in body;","typeGuard":"function isInferencePayload(p: unknown): p is Record<string, unknown> {\n  return typeof p === \"object\" && p !== null && \"enabled\" in p && \"organization\" in p;\n}","tryCatchPattern":"try {\n  const { response, payload } = await requestJson(\"/v1/inference\", { method: \"GET\" }, 12000);\n  if (!response.ok) throw new Error(getErrorMessage(payload, `Failed to load inference settings (${response.status}).`));\n  const parsed = parseInferencePayload(payload);\n  if (!parsed) throw new Error(\"Inference settings response was incomplete.\");\n} catch (e) {\n  setError(e instanceof Error ? e.message : \"Failed to load inference settings.\");\n}","preventionTips":["Pin dashboard and server to matching versions so the /v1/inference contract stays aligned.","Log raw payloads when parsing fails to speed up contract-drift debugging.","Add a contract test asserting parseInferencePayload accepts the live server response.","Ensure proxies never replace JSON bodies with HTML (check Accept headers)."],"tags":["api-contract","schema-validation","http"],"backgroundTag":"schema-validation-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}