different-ai/openwork · error · Error

Failed to grant access (${response.status}).

Error message

Failed to grant access (${response.status}).

What it means

Thrown by useGrantMarketplaceAccess in marketplace-data.tsx when POST /v1/marketplaces/{marketplaceId}/access (15s timeout) returns non-ok. getRequestError (den-flow.ts:527) turns a 403 {error:'reauth'} payload into ReauthRequiredError and otherwise yields the server `error` message or the fallback "Failed to grant access (<status>).".

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/marketplace-data.tsx:299

      body:
        | { orgWide: true; role?: MarketplaceAccessRole }
        | { teamId: string; role?: MarketplaceAccessRole }
        | { orgMembershipId: string; role?: MarketplaceAccessRole };
    }) => {
      await runReauthableAction("grant-marketplace-access", async () => {
      const body = {
        role: input.body.role ?? "viewer",
        ...("orgWide" in input.body ? { orgWide: true } : {}),
        ...("teamId" in input.body ? { teamId: input.body.teamId } : {}),
        ...("orgMembershipId" in input.body ? { orgMembershipId: input.body.orgMembershipId } : {}),
      };
      const { response, payload } = await requestJson(
        `/v1/marketplaces/${encodeURIComponent(input.marketplaceId)}/access`,
        { method: "POST", body: JSON.stringify(body) },
        15000,
      );
      if (!response.ok) {
        throw getRequestError(payload, response, `Failed to grant access (${response.status}).`);
      }
      });
      return input.marketplaceId;
    },
    onSuccess: (marketplaceId) => {
      queryClient.invalidateQueries({ queryKey: marketplaceQueryKeys.access(marketplaceId) });
      queryClient.invalidateQueries({ queryKey: marketplaceQueryKeys.resolved(marketplaceId) });
    },
  });
}

export function useRevokeMarketplaceAccess() {
  const queryClient = useQueryClient();
  const { runReauthableAction } = useOrgDashboard();

  return useMutation({
    mutationFn: async (input: { marketplaceId: string; grantId: string }) => {
      await runReauthableAction("revoke-marketplace-access", async () => {

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. On 409, treat as success: the grant already exists — invalidate marketplaceQueryKeys.access(marketplaceId) and update the UI.
  2. On 404, refresh the marketplace and member lists; the marketplace or grantee is gone.
  3. For 403, confirm admin/owner role and complete reauth when isReauthRequiredError(error) is true.
  4. On 429, check the org plan/seat limits before retrying the grant.

Example fix

// before
if (!response.ok) {
  throw getRequestError(payload, response, `Failed to grant access (${response.status}).`);
}
// after
if (!response.ok) {
  if (response.status === 409) return input.marketplaceId; // already granted
  throw getRequestError(payload, response, `Failed to grant access (${response.status}).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before granting
if (!marketplaceId) throw new Error("marketplaceId is required.");
if (!granteeIds.length) throw new Error("Select at least one member or team.");
const missing = granteeIds.filter((id) => !activeMembers.some((m) => m.id === id));
if (missing.length) throw new Error(`Unknown grantee(s): ${missing.join(", ")}`);

Type guard

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

Try / catch

try {
  await grantMutation.mutateAsync({ marketplaceId, ...body });
} catch (error) {
  if (isReauthError(error)) { startReauth(); return; }
  if (/\(409\)/.test(error.message)) { await queryClient.invalidateQueries(marketplaceQueryKeys.access(marketplaceId)); return; }
  showToast(error.message);
}

Prevention

When it happens

Trigger: Granting a member/team access to a private marketplace returns non-ok: 401/403 (caller is not an org owner/admin or session expired), 404 (marketplace id or grantee id does not exist), 409 (access already granted), 422 (invalid grantee or body), 429 (plan/seat limits on marketplace access), 5xx, or the 15s timeout.

Common situations: Granting to a user removed from the org; duplicating a grant from double-click; non-admin opening the marketplace share dialog; grant body missing required fields after a marketplace schema change on the server.

Related errors


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