different-ai/openwork · error

Failed to verify domain (${response.status}).

Error message

Failed to verify domain (${response.status}).

What it means

Thrown by handleVerifyDomain when POST /v1/sso/verify-domain returns a status other than 204 or generic non-ok. The server checks the org's DNS TXT record for the issued domainVerificationToken; failure here is usually that the DNS record has not propagated or does not match. Success clears the token and reloads the SSO config.

Source

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

    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : "Failed to request domain verification.");
    }
  }

  async function handleVerifyDomain() {
    if (!access.canManageSso) {
      setError("Only workspace owners and super-admins can verify SSO domains.");
      return;
    }
    if (!orgId || !connection) return;
    setError(null);
    try {
      await runReauthableAction("verify-sso-domain", async () => {
        setVerifyingDomain(true);
        try {
          const { response, payload } = await requestJson("/v1/sso/verify-domain", { method: "POST", headers: getOrgScopedHeaders(), body: JSON.stringify({}) }, 12000);
          if (response.status !== 204 && !response.ok) {
            throw getRequestError(payload, response, `Failed to verify domain (${response.status}).`);
          }
          setDomainVerificationToken(null);
          await loadSsoConfig();
        } finally {
          setVerifyingDomain(false);
        }
      });
    } catch (nextError) {
      setError(nextError instanceof Error ? nextError.message : "Failed to verify the SSO domain.");
    }
  }

  function handleCancelEdit() {
    syncFormFromConnection(connection);
    setEditing(false);
  }

  const formReadOnly = !access.canManageSso;

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Confirm the TXT record exists via `dig TXT yourdomain.com +short` and exactly matches the issued domainVerificationToken (watch extra quotes).
  2. Wait for DNS propagation (TTL up to hours) and retry — 409/422 here is almost always propagation lag.
  3. If the token expired (404), call handleRequestDomainToken again to re-issue, publish, then verify.
  4. Ensure a token was requested in this session (domainVerificationToken !== null) before verifying.
  5. Handle ReauthRequiredError via re-authentication and check admin permissions for 403.

Example fix

// before: immediate verify after showing token
setDomainVerificationToken(token);
await handleVerifyDomain();
// after: guide the user through DNS first
setDomainVerificationToken(token);
setError(`Add TXT record _openwork to your domain with value ${token}, then verify after it propagates.`);
// verification stays user-triggered; on 409/422 show retry-later message
Defensive patterns

Strategy: retry

Validate before calling

if (!domainVerificationToken) { setError("Request a domain verification token first."); return; }
// before verifying, optionally pre-check DNS from the client (informational only):
// const txt = await fetch(`https://dns.google/resolve?name=_openwork.${domain}&type=TXT`)

Type guard

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

Try / catch

try {
  await verifyDomain();
} catch (err) {
  if (isReauthRequiredError(err)) { promptSignIn(); return; }
  if (/\b(409|422)\b/.test(err.message)) {
    setError("TXT record not found yet — wait for DNS propagation and try again.");
    return; // retryable
  }
  if (/\b404\b/.test(err.message)) { setError("Verification request expired; request a new token."); return; }
  setError(err.message);
}

Prevention

When it happens

Trigger: POST /v1/sso/verify-domain with org-scoped headers returns 400 (no pending domainVerificationToken was requested), 401 (expired session), 403 (not org admin / reauth challenge), 404 (verification request expired), 409/422 (TXT record not found or mismatched — DNS not propagated), 429, or 5xx. 12s timeout.

Common situations: Verifying minutes after adding the TXT record while DNS TTL hasn't elapsed; TXT record added to the wrong domain/subdomain or with wrong quoting; token expired and needs re-issue; the org never requested a token in this session.

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/00f0f1e4ca34ffd5. Report an issue: GitHub.