different-ai/openwork · error

Only workspace admins can cancel invitations.

Error message

Only workspace admins can cancel invitations.

What it means

cancelInvitation requires access.canCancelInvitations before it will POST /v1/invitations/{id}/cancel. If the current member is not a workspace admin (per getOrgAccessFlags), the provider throws "Only workspace admins can cancel invitations." and no network request is made. It is the client-side authorization gate for revoking pending org invitations.

Source

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

        }

        const url = payload && typeof payload === "object" && "url" in payload && typeof payload.url === "string"
          ? payload.url
          : null;
        if (!url) {
          throw new Error("Seat billing checkout response did not include a URL.");
        }

        window.location.href = url;
      });
    } finally {
      setMutationBusy(null);
    }
  }

  async function cancelInvitation(invitationId: string) {
    if (!getCurrentAccess().canCancelInvitations) {
      throw new Error("Only workspace admins can cancel invitations.");
    }

    await runMutation("cancel-invitation", async () => {
      ensureActiveOrganizationSelected();
      const { response, payload } = await requestJson(
        `/v1/invitations/${encodeURIComponent(invitationId)}/cancel`,
        { method: "POST", body: JSON.stringify({}) },
        12000,
      );

      if (!response.ok) {
        throw getRequestError(payload, response, `Failed to cancel invitation (${response.status}).`);
      }
    });
  }

  async function updateMemberRole(memberId: string, role: string) {
    if (!getCurrentAccess().canManageRoles) {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. Have a workspace admin cancel the invitation.
  2. Check your role in the active organization before managing invitations.
  3. Refresh org context to pick up recent role changes and retry if you were promoted.
  4. Render cancel controls only when access.canCancelInvitations is true.

Example fix

// before
{invitations.map((inv) => (
  <Button onClick={() => cancelInvitation(inv.id)}>Revoke</Button>
))}

// after
{access.canCancelInvitations && invitations.map((inv) => (
  <Button onClick={() => cancelInvitation(inv.id)}>Revoke</Button>
))}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!access.canCancelInvitations) return; // don't render or call cancelInvitation

Try / catch

try {
  await cancelInvitation(invitationId);
} catch (e) {
  if (e instanceof Error && e.message.startsWith("Only workspace admins")) {
    toast(e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling cancelInvitation(invitationId) (e.g. from ManageMembersScreen's pending-invitations list) while the signed-in member's resolved role lacks canCancelInvitations.

Common situations: A non-admin member opens the members screen and clicks Revoke on a pending invite; role was downgraded but the UI still shows cancel buttons; stale orgContext after switching organizations.

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