different-ai/openwork · error

Failed to load SSO settings

Error message

Failed to load SSO settings (${response.status}).

What it means

Thrown by loadSsoConfig when GET /v1/sso returns a non-ok status. This query loads the organization's SSO connection, form state, and domain verification token; on success it populates connection state via parseOrgSsoPayload. The request uses getOrgScopedHeaders() so an invalid/missing org scope or expired session commonly causes rejection. getRequestError may raise ReauthRequiredError for 403 error:'reauth'.

Solutions

  1. Check the status and appended server message in the thrown error.
  2. If 403 with reauth, wrap loadSsoConfig in runReauthableAction (the handlers already do; direct callers may not).
  3. Verify getOrgScopedHeaders() contains a valid, current organization id and that the user is an org admin.
  4. Re-authenticate on 401 and reload; the UI's setError path should prompt sign-in.
  5. For 5xx/HTML payloads, check Den server/proxy health and retry.

Example fix

// before: load without guard
await loadSsoConfig();
// after
try {
  await runReauthableAction("load-sso", () => loadSsoConfig());
} catch (err) {
  setError(isReauthRequiredError(err) ? "Sign in again to view SSO settings." : getErrorMessage(err, "Failed to load SSO settings."));
}
Defensive patterns

Strategy: try-catch

Validate before calling

const headers = getOrgScopedHeaders();
if (!headers || !orgId) throw new Error("Select an organization before loading SSO settings.");

Type guard

function isReauthRequiredError(e: unknown): e is ReauthRequiredError {
  return e instanceof ReauthRequiredError;
}

Try / catch

try {
  await loadSsoConfig();
} catch (err) {
  if (isReauthRequiredError(err)) { promptSignIn(); return; }
  if (/\b403\b/.test(err.message)) { setError("Org admin access required."); return; }
  setError(err.message);
}

Prevention

When it happens

Trigger: GET /v1/sso with org-scoped headers returns 401 (session expired), 403 (user lacks org admin/read SSO settings permission, or reauth challenge; also wrong/unset org scope header), 404 (SSO not configured for this org — depends on server semantics), 429, or 5xx. 12s timeout.

Common situations: Member (non-admin) opens the SSO settings screen; org header points to an org the user doesn't belong to; long-idle tab with expired token; Den server returning HTML error pages through a proxy.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01). Data as JSON: /api/errors/0d79a401b6e5065e. Report an issue: GitHub.

Appendix: source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/sso-screen.tsx:70

    [orgContext?.currentMember.isOwner, orgContext?.currentMember.role, orgContext?.roles],
  );

  async function loadSsoConfig(isCurrent = () => true) {
    if (!orgId || !access.canViewSettings) {
      if (isCurrent()) {
        setConnection(null);
      }
      return;
    }

    if (isCurrent()) {
      setBusy(true);
      setError(null);
    }
    try {
      const { response, payload } = await requestJson("/v1/sso", { method: "GET", headers: getOrgScopedHeaders() }, 12000);
      if (!response.ok) {
        throw getRequestError(payload, response, `Failed to load SSO settings (${response.status}).`);
      }

      const parsed = parseOrgSsoPayload(payload);
      if (isCurrent()) {
        setConnection(parsed.connection);
        syncFormFromConnection(parsed.connection);
        setEditing(false);
      }
    } catch (nextError) {
      if (isReauthRequiredError(nextError)) {
        throw nextError;
      }

      if (isCurrent()) {
        setError(nextError instanceof Error ? nextError.message : "Failed to load SSO settings.");
      }
    } finally {
      if (isCurrent()) {

View on GitHub (pinned to 2b7df46e8a)