{"record":{"id":"dbe10ccfa485355a","repo":"different-ai/openwork","slug":"scim-token-rotation-succeeded-but-the-response-wa","errorCode":null,"errorMessage":"SCIM token rotation succeeded, but the response was incomplete.","messagePattern":"SCIM token rotation succeeded, but the response was incomplete\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/scim-screen.tsx","lineNumber":180,"sourceCode":"    setError(null);\n    setVisibleToken(null);\n    try {\n      await runReauthableAction(\"rotate-scim-token\", async () => {\n        setRotating(true);\n        try {\n          const { response, payload } = await requestJson(\n            \"/v1/scim/token\",\n            { method: \"POST\", body: JSON.stringify({}) },\n            12000,\n          );\n\n          if (!response.ok) {\n            throw getRequestError(payload, response, `Failed to rotate SCIM token (${response.status}).`);\n          }\n\n          const parsed = parseOrgScimPayload(payload);\n          if (!parsed.baseUrl || !parsed.connection || !parsed.scimToken) {\n            throw new Error(\"SCIM token rotation succeeded, but the response was incomplete.\");\n          }\n\n          setBaseUrl(parsed.baseUrl);\n          setSsoReady(parsed.ssoReady);\n          setConnection(parsed.connection);\n          setHealth(parsed.health);\n          setVisibleToken(parsed.scimToken);\n          setCopiedValue(null);\n        } finally {\n          setRotating(false);\n        }\n      });\n    } catch (nextError) {\n      setError(\n        nextError instanceof Error ? nextError.message : \"Failed to rotate SCIM token.\",\n      );\n    }\n  }","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/scim-screen.tsx#L162-L198","documentation":"After a successful SCIM token rotation request, handleRotateToken parses the response with parseOrgScimPayload and requires baseUrl, connection, and scimToken to all be present before updating UI state. If any of the three is missing, it throws this error. The rotation itself succeeded — the server likely rotated the token — but the client cannot display the new connection state, and the new token value may be lost if not shown here.","triggerScenarios":"POST to the SCIM rotate-token endpoint returns ok but the payload lacks baseUrl, connection, or scimToken — e.g. the API only returns the new token, omits the connection object for partially configured orgs, or returns a wrapped envelope parseOrgScimPayload doesn't unwrap.","commonSituations":"Org with SSO configured but SCIM connection not yet provisioned; API response envelope change ({ data: ... }); server redacting scimToken for security in newer versions; stale frontend expecting a field the API no longer returns.","solutions":["Log/inspect the rotate response payload and confirm which of baseUrl/connection/scimToken is missing","Update parseOrgScimPayload to unwrap the actual response envelope","Fix the rotate endpoint to return the full SCIM config (baseUrl, connection, scimToken) after rotation","If the token is intentionally redacted after rotation, redesign the UI to show the token only from the rotate response and stop requiring it here"],"exampleFix":"// before\nif (!parsed.baseUrl || !parsed.connection || !parsed.scimToken) {\n  throw new Error(\"SCIM token rotation succeeded, but the response was incomplete.\");\n}\n// after\nif (!parsed.scimToken || !parsed.connection) {\n  throw new Error(`SCIM token rotation response incomplete (baseUrl=${Boolean(parsed.baseUrl)}, connection=${Boolean(parsed.connection)}, token=${Boolean(parsed.scimToken)}).`);\n}\nif (parsed.baseUrl) setBaseUrl(parsed.baseUrl);","handlingStrategy":"validation","validationCode":"function parseOrgScimPayload(payload: unknown): { baseUrl?: string; connection?: unknown; scimToken?: string; ssoReady?: boolean; health?: unknown } {\n  const body = typeof payload === \"object\" && payload !== null && \"data\" in payload ? (payload as { data: unknown }).data : payload;\n  return (body ?? {}) as Record<string, never>;\n}\n// pre-check before trusting state updates:\nconst missing = [!parsed.baseUrl && \"baseUrl\", !parsed.connection && \"connection\", !parsed.scimToken && \"scimToken\"].filter(Boolean);","typeGuard":"function isCompleteScimRotation(p: { baseUrl?: unknown; connection?: unknown; scimToken?: unknown }): p is { baseUrl: string; connection: Record<string, unknown>; scimToken: string } {\n  return typeof p.baseUrl === \"string\" && p.baseUrl.length > 0 && typeof p.connection === \"object\" && p.connection !== null && typeof p.scimToken === \"string\" && p.scimToken.length > 0;\n}","tryCatchPattern":"try {\n  const parsed = parseOrgScimPayload(payload);\n  if (!isCompleteScimRotation(parsed)) {\n    throw new Error(\"SCIM token rotation succeeded, but the response was incomplete.\");\n  }\n  setBaseUrl(parsed.baseUrl);\n} catch (error) {\n  setError(error instanceof Error ? error.message : \"Failed to rotate SCIM token.\");\n}","preventionTips":["Have the rotate endpoint return the full SCIM config atomically and cover it with a contract test","Log (redacted) rotation payloads during development to catch envelope drift early","Never require a secret (scimToken) in later GET responses — only in the rotation response","Version the SCIM API response schema and validate with Zod at the boundary"],"tags":["scim","api","response-parsing"],"backgroundTag":"api-response-missing-field","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}