{"record":{"id":"63924a31864c8f16","repo":"different-ai/openwork","slug":"profile-update-response-did-not-include-a-user","errorCode":null,"errorMessage":"Profile update response did not include a user.","messagePattern":"Profile update response did not include a user\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/_providers/den-flow-provider.tsx","lineNumber":1425,"sourceCode":"  }\n\n  async function updateUserProfile(input: { firstName: string; lastName: string }) {\n    const { response, payload } = await requestJson(\n      \"/v1/me/profile\",\n      {\n        method: \"PATCH\",\n        body: JSON.stringify(input),\n      },\n      12000,\n    );\n\n    if (!response.ok) {\n      throw new Error(getErrorMessage(payload, `Failed to update profile (${response.status}).`));\n    }\n\n    const nextUser = getUser(payload);\n    if (!nextUser) {\n      throw new Error(\"Profile update response did not include a user.\");\n    }\n\n    setUser(nextUser);\n    identifyPosthogUser(nextUser);\n    return nextUser;\n  }\n\n  async function launchWorker(options: { source?: \"manual\" | \"signup_auto\"; workerNameOverride?: string } = {}) {\n    if (!user) {\n      setAuthError(\"Sign in before launching a worker.\");\n      return \"error\" as const;\n    }\n\n    const resolvedLaunchName = options.workerNameOverride?.trim() || workerName.trim() || DEFAULT_WORKER_NAME;\n\n    setLaunchBusy(true);\n    setLaunchError(null);\n    setOrgLimitError(null);","sourceCodeStart":1407,"sourceCodeEnd":1443,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/_providers/den-flow-provider.tsx#L1407-L1443","documentation":"updateProfile in DenFlowProvider calls the Den API to update the user's profile and expects the response body to contain a user object extractable via getUser(payload). If the HTTP call succeeds but the payload lacks a recognizable user shape, this error is thrown so the app never sets an undefined user into context. It indicates an API contract mismatch between client and server.","triggerScenarios":"The PUT/PATCH profile endpoint returns 2xx with an empty body, a wrapped envelope like {data:{...}} instead of {user:{...}} (or whatever getUser expects), or a partial-update response that only returns the changed fields.","commonSituations":"Server deployed at a different version than the web client after an API contract change; a proxy stripping or reshaping the response; hitting a mock/stub endpoint that returns {} with 200.","solutions":["Inspect the actual response payload in devtools/network tab and compare with what getUser(payload) expects (field name and shape).","Check that the den-web client and den server versions match; redeploy whichever is stale.","If the server intentionally returns an envelope, update getUser in the provider to unwrap it.","Add a server-side fix to always return the full user object on profile update."],"exampleFix":"// before\nconst nextUser = getUser(payload);\nif (!nextUser) throw new Error(\"Profile update response did not include a user.\");\n// after\nconst rawUser = payload?.user ?? payload?.data?.user;\nconst nextUser = rawUser ? getUser({ user: rawUser }) : undefined;\nif (!nextUser) throw new Error(\"Profile update response did not include a user.\");","handlingStrategy":"validation","validationCode":"function hasUser(p: unknown): boolean {\n  return typeof p === \"object\" && p !== null && \"user\" in p && typeof (p as {user:unknown}).user === \"object\";\n}\nif (!hasUser(payload)) { /* don't call updateProfile-dependent UI */ }","typeGuard":"function isUser(u: unknown): u is { id: string; email: string } {\n  return typeof u === \"object\" && u !== null && \"id\" in u && \"email\" in u;\n}","tryCatchPattern":"try {\n  await updateProfile(data);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"did not include a user\")) {\n    showToast(\"Profile saved but response was malformed — reloading.\");\n    await refetchUser();\n  } else throw err;\n}","preventionTips":["Keep client getUser() in sync with the server's profile-update response schema.","Add a Zod schema over the update response and test it in CI against the real endpoint shape.","Pin and deploy client and server together so contract changes land atomically.","Log raw payloads on this error to speed up contract-mismatch diagnosis."],"tags":["api-contract","response-parsing","den-api"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}