{"record":{"id":"984bb457d515cbc5","repo":"different-ai/openwork","slug":"failed-to-save-sso-settings-response-status","errorCode":null,"errorMessage":"Failed to save SSO settings (${response.status}).","messagePattern":"Failed to save SSO settings \\((.+?)\\)\\.","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/sso-screen.tsx","lineNumber":194,"sourceCode":"                audience: audience || undefined,\n              }\n            : {\n                issuer,\n                domain,\n                clientId,\n                clientSecret,\n                scopes: scopes.split(/\\s+/).map((entry) => entry.trim()).filter(Boolean),\n                skipDiscovery,\n                authorizationEndpoint: authorizationEndpoint || undefined,\n                tokenEndpoint: tokenEndpoint || undefined,\n                jwksEndpoint: jwksEndpoint || undefined,\n                userInfoEndpoint: userInfoEndpoint || undefined,\n                tokenEndpointAuthentication: tokenEndpointAuthentication || undefined,\n              };\n\n          const { response, payload } = await requestJson(path, { method: \"POST\", headers: getOrgScopedHeaders(), body: JSON.stringify(body) }, 20000);\n          if (!response.ok) {\n            throw getRequestError(payload, response, `Failed to save SSO settings (${response.status}).`);\n          }\n\n          const parsed = parseOrgSsoPayload(payload);\n          setConnection(parsed.connection);\n          syncFormFromConnection(parsed.connection);\n          setDomainVerificationToken(parsed.domainVerificationToken);\n          setEditing(false);\n        } finally {\n          setSaving(false);\n        }\n      });\n    } catch (nextError) {\n      setError(nextError instanceof Error ? nextError.message : \"Failed to save SSO settings.\");\n    }\n  }\n\n  async function handleDelete() {\n    if (!access.canManageSso) {","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/sso-screen.tsx#L176-L212","documentation":"Thrown by handleSave when POST /v1/sso (or the create/update path variant held in `path`) returns non-ok. The body carries the full OIDC/SAML connection definition (issuer, clientId, endpoints, tokenEndpointAuthentication, etc.), so this is typically server-side validation of the SAML/OIDC metadata or a permissions problem. On success the parsed connection and domain verification token are written back into form state.","triggerScenarios":"POST /v1/sso with org-scoped headers and the connection body returns 400 (invalid IdP metadata, malformed URLs, bad tokenEndpointAuthentication value), 401 (expired session), 403 (not org admin / reauth challenge), 409 (conflicting existing connection or already-verified domain), 422 (schema validation), 429, or 5xx. 20s timeout (longest of the SSO calls).","commonSituations":"Typo in issuer/issuer URL or endpoints (must be https); pasting metadata from an IdP with unsupported auth method like client_secret_jwt; non-admin tries to save; domain already claimed by another org.","solutions":["Read the server's message/error appended to the thrown error — validation details (which field) are usually included.","Fix form values: issuer, endpoints, and tokenEndpointAuthentication must match what the IdP actually exposes (https URLs, supported auth scheme).","If 403, confirm the user is an org admin and handle ReauthRequiredError via runReauthableAction.","If 409 on domain, the domain is claimed elsewhere — verify ownership flow or use a different domain.","Check network tab for exact status; re-try after fixing inputs rather than resubmitting identical payload."],"exampleFix":"// before: save whatever the form holds\nconst body = { issuer, clientId, userInfoEndpoint: userInfoEndpoint || undefined, ... };\nawait requestJson(path, { method: \"POST\", headers: getOrgScopedHeaders(), body: JSON.stringify(body) }, 20000);\n// after: validate URLs first\nconst urls = [issuer, authorizationEndpoint, tokenEndpoint, userInfoEndpoint].filter(Boolean);\nif (urls.some((u) => !u.startsWith(\"https://\"))) {\n  setError(\"All endpoints must be https:// URLs.\");\n  return;\n}\n// ... then POST as before","handlingStrategy":"validation","validationCode":"function validateSsoForm(f: {\n  issuer: string; clientId: string;\n  authorizationEndpoint?: string; tokenEndpoint?: string; userInfoEndpoint?: string;\n  tokenEndpointAuthentication?: string;\n}): string | null {\n  if (!f.issuer.trim()) return \"Issuer is required.\";\n  if (!f.clientId.trim()) return \"Client ID is required.\";\n  const urls = [f.issuer, f.authorizationEndpoint, f.tokenEndpoint, f.userInfoEndpoint].filter(Boolean);\n  if (urls.some((u) => !/^https:\\/\\//.test(u))) return \"All endpoints must be https URLs.\";\n  if (f.tokenEndpointAuthentication && ![\"client_secret_basic\",\"client_secret_post\"].includes(f.tokenEndpointAuthentication))\n    return \"Unsupported token endpoint authentication method.\";\n  return null;\n}\nconst problem = validateSsoForm(form); if (problem) { setError(problem); return; }","typeGuard":"function isHttpUrl(v: string): boolean {\n  try { const u = new URL(v); return u.protocol === \"https:\"; } catch { return false; }\n}","tryCatchPattern":"try {\n  await saveSso(body);\n} catch (err) {\n  if (isReauthRequiredError(err)) { promptSignIn(); return; }\n  // server validation messages land here — surface them next to the form\n  setFieldErrorsFromServer(err.message);\n}","preventionTips":["Validate every endpoint URL is https and well-formed before POST.","Only enable Save for org admins.","Match tokenEndpointAuthentication to what the IdP actually supports.","On 409 (domain claimed), stop resubmitting and guide the user to domain verification or a different domain.","Keep the 20s timeout; SAML metadata fetch can be slow — don't retry aggressively on timeout."],"tags":["http","sso","validation","oidc","saml","den-web"],"backgroundTag":"http-request-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}