different-ai/openwork · error

Only workspace admins can start seat checkout.

Error message

Only workspace admins can start seat checkout.

What it means

startSeatCheckout gates the seat-billing checkout flow behind access.canStartSeatCheckout. Only workspace admins (owners/super-admins per getOrgAccessFlags) may begin a seat checkout; any other role throws "Only workspace admins can start seat checkout." before any billing request is made. This is a client-side RBAC check, consistent with server enforcement.

Source

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

      if (!response.ok) {
        const paymentRequiredError = getOrgPaymentRequiredError(payload);
        if (paymentRequiredError) {
          throw paymentRequiredError;
        }

        const limitError = getOrgLimitError(payload);
        if (limitError) {
          throw limitError;
        }
        throw getRequestError(payload, response, `Failed to invite member (${response.status}).`);
      }
    });
  }

  async function startSeatCheckout() {
    if (!getCurrentAccess().canStartSeatCheckout) {
      throw new Error("Only workspace admins can start seat checkout.");
    }

    setMutationBusy("seat-checkout");
    setOrgError(null);
    try {
      await runReauthableAction("seat-checkout", async () => {
        ensureActiveOrganizationSelected();
        const { response, payload } = await requestJson(
          "/v1/billing/stripe/checkout",
          {
            method: "POST",
            body: JSON.stringify({ type: "seat" }),
          },
          12000,
        );

        if (!response.ok) {
          throw getRequestError(payload, response, `Seat billing checkout failed (${response.status}).`);

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Have a workspace admin perform the seat checkout.
  2. Confirm your role in the active organization and switch to an org where you are admin if applicable.
  3. Reload the dashboard to refresh orgContext/access flags if your role was recently promoted.
  4. Conditionally render the seat-checkout CTA on canStartSeatCheckout.

Example fix

// before
<button onClick={() => startSeatCheckout()}>Buy seats</button>

// after
{access.canStartSeatCheckout && (
  <button onClick={() => startSeatCheckout()}>Buy seats</button>
)}
Defensive patterns

Strategy: validation

Validate before calling

if (!access.canStartSeatCheckout) return; // gate the CTA before calling startSeatCheckout()

Try / catch

try {
  await startSeatCheckout();
} catch (e) {
  if (e instanceof Error && e.message.includes("start seat checkout")) {
    showNotice("Contact a workspace admin to purchase seats.");
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking startSeatCheckout() (e.g. from a "Buy more seats" button) when the current member's role is not admin-level, so canStartSeatCheckout is false.

Common situations: A non-admin member clicks a seat-purchase CTA that should have been hidden; billing UI rendered based on stale access flags after a role change; switching to an org where the user is only a member.

Understand the failure class

Background: "You do not have permission" / 403 Forbidden errors: authenticated but not allowed — causes and fixes across open-source libraries — this error's family across 31 libraries.

Related errors


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