different-ai/openwork · error

Failed to create organization (${response.status}).

Error message

Failed to create organization (${response.status}).

What it means

createOrganization POSTs { name } to the server (12s timeout) and throws this error when the response is not ok. The organization was not created; the message carries the HTTP status unless the payload includes a server error message via getErrorMessage.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_providers/org-dashboard-provider.tsx:442

    const trimmed = name.trim();
    if (!trimmed) {
      throw new Error("Enter an organization name.");
    }

    setMutationBusy("create-organization");
    setOrgError(null);
    try {
      const { response, payload } = await requestJson(
        "/v1/org",
        {
          method: "POST",
          body: JSON.stringify({ name: trimmed }),
        },
        12000,
      );

      if (!response.ok) {
        throw new Error(getErrorMessage(payload, `Failed to create organization (${response.status}).`));
      }

      const organization =
        typeof payload === "object" && payload && "organization" in payload && payload.organization && typeof payload.organization === "object"
          ? payload.organization as { slug?: unknown }
          : null;
      const nextSlug = typeof organization?.slug === "string" ? organization.slug : null;

      if (!nextSlug) {
        throw new Error("Organization was created, but no slug was returned.");
      }

      router.push(getOrgDashboardRoute(nextSlug));
    } finally {
      setMutationBusy(null);
    }
  }

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Read the status: 409/422 → pick a different organization name (server enforces unique slugs).
  2. 403 → verify the deployment allows user-created orgs (not single-org mode) and that the user's role permits creation.
  3. 401 → re-authenticate, then resubmit the form preserving the entered name.
  4. Inspect the response payload message (getErrorMessage extracts the server's detail) for the precise rejection reason.
  5. For 5xx, check den-api logs; if the org was actually created despite the error (timeout after write), check the org list before retrying to avoid duplicates.

Example fix

// before
await createOrganization(name); // 409 on duplicate
// after
try {
  await createOrganization(name);
} catch (err) {
  if (String(err).includes("409") || String(err).includes("422")) {
    setOrgError("That organization name is already taken. Choose another.");
    return;
  }
  throw err;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check for duplicate names locally before POST
const existing = await loadOrgDirectory();
if (existing.some(o => o.name.toLowerCase() === name.trim().toLowerCase())) {
  throw new Error("An organization with this name already exists.");
}

Try / catch

try {
  await createOrganization(name);
} catch (err) {
  const m = err.message;
  if (m.includes("409") || m.includes("422")) showNameTakenError();
  else if (m.includes("401")) await reauthThenRetry(name);
  else if (m.includes("403")) showNoPermissionError();
  else throw err;
}

Prevention

When it happens

Trigger: POST create-org returns 401 (expired session), 403 (user lacks permission to create orgs on this deployment), 409 (name/slug conflict with an existing org), 422 (name rejected by server validation, e.g., duplicate or reserved slug), or 5xx.

Common situations: Choosing an organization name that already exists (unique slug constraint); users without the create-org entitlement; Den server error during DB write; session expiring mid-form.

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/5b824d371fd21503. Report an issue: GitHub.