{"record":{"id":"07f86617faae8182","repo":"different-ai/openwork","slug":"failed-to-reconcile-scim-response-status","errorCode":null,"errorMessage":"Failed to reconcile SCIM (${response.status}).","messagePattern":"Failed to reconcile SCIM \\((.+?)\\)\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/scim-screen.tsx","lineNumber":223,"sourceCode":"\n    if (!orgId) {\n      setError(\"Organization not found.\");\n      return;\n    }\n\n    setError(null);\n    try {\n      await runReauthableAction(\"reconcile-scim\", async () => {\n        setReconciling(true);\n        try {\n          const { response, payload } = await requestJson(\n            \"/v1/scim/reconcile\",\n            { method: \"POST\", body: JSON.stringify({}) },\n            12000,\n          );\n\n          if (!response.ok) {\n            throw getRequestError(payload, response, `Failed to reconcile SCIM (${response.status}).`);\n          }\n\n          await loadScimConfig();\n        } finally {\n          setReconciling(false);\n        }\n      });\n    } catch (nextError) {\n      setError(\n        nextError instanceof Error ? nextError.message : \"Failed to reconcile SCIM.\",\n      );\n    }\n  }\n\n  async function handleGroupMappingChange() {\n    if (!access.canManageScim) {\n      setError(\"Only workspace owners and super-admins can change SCIM mappings.\");\n      return;","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/scim-screen.tsx#L205-L241","documentation":"handleRunReconciliation in scim-screen.tsx throws this when POST /v1/scim/reconcile returns non-ok. Reconciliation pushes org group/user mappings to the identity provider and can be slow; the error means the server rejected or failed the run. After success the code reloads the SCIM config; after this throw the reconcile flag is reset in finally.","triggerScenarios":"POST /v1/scim/reconcile with empty body returns 401/403 (auth/permission), 404 (no SCIM connection), 409 (a reconcile run is already in progress), 422 (identity provider rejects the sync), or 5xx/timeout (reconcile exceeding the 12s window on large directories).","commonSituations":"Large orgs where reconciliation takes longer than the client timeout; IdP credentials revoked or token rotated but not yet synced; double-clicking the reconcile button triggering concurrent runs.","solutions":["For timeouts on large directories, retry — or run reconciliation server-side/off-peak and poll status.","Check status 401/403: re-authenticate or use an admin account.","404: provision the SCIM connection before reconciling.","Disable the reconcile button while a run is pending to avoid 409s."],"exampleFix":"// before: button stays clickable during a run\n<button onClick={handleRunReconciliation}>Reconcile</button>\n// after: disable while running\n<button disabled={reconciling} onClick={handleRunReconciliation}>Reconcile</button>","handlingStrategy":"retry","validationCode":"if (reconciling) return; // already in progress\nif (!connection) throw new Error('Provision the SCIM connection before reconciling.');","typeGuard":"function canReconcile(v: unknown): v is { connection: unknown; reconciling: false } {\n  return typeof v === 'object' && v !== null &&\n    (v as Record<string, unknown>).connection != null &&\n    (v as Record<string, unknown>).reconciling === false;\n}","tryCatchPattern":"try {\n  await runReconciliation();\n  toast('Reconciliation started.');\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (/timed out|\\(5\\d\\d\\)/i.test(msg)) toast('Reconciliation is still running server-side; check status shortly.');\n  else if (msg.includes('409')) toast('A reconciliation is already in progress.');\n  else toast(msg);\n}","preventionTips":["Disable the reconcile button while a run is pending to prevent 409s.","Expect large directories to exceed the 12s client timeout — treat timeout as 'started', not 'failed'.","Ensure SCIM token/IdP credentials are current before reconciling.","Schedule heavy reconciles off-peak."],"tags":["http","api","scim","sync"],"backgroundTag":"http-non-ok-response","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}