different-ai/openwork · error

Failed to revoke dashboard access (${response.status}).

Error message

Failed to revoke dashboard access (${response.status}).

What it means

Thrown by useRevokeDashboardAccess when DELETE /v1/dashboards/:id/access/:grantId returns neither 204 nor ok. Like the sibling delete mutation, non-204 success bodies are tolerated; anything else non-ok raises this error with the status in the message.

Source

Thrown at ee/apps/den-web/app/(den)/dashboard/_components/org-dashboards-data.tsx:359

      queryClient.invalidateQueries({ queryKey: orgDashboardsQueryKeys.access(organizationId, dashboardId) });
    },
  });
}

export function useRevokeDashboardAccess() {
  const queryClient = useQueryClient();
  const { orgContext, runReauthableAction } = useOrgDashboard();
  const organizationId = orgContext?.organization.id ?? "";
  return useMutation({
    mutationFn: async (input: { dashboardId: string; grantId: string }) => {
      await runReauthableAction("revoke-dashboard-access", async () => {
        const { response, payload } = await requestJson(
          `/v1/dashboards/${encodeURIComponent(input.dashboardId)}/access/${encodeURIComponent(input.grantId)}`,
          { method: "DELETE" },
          15000,
        );
        if (response.status !== 204 && !response.ok) {
          throw getRequestError(payload, response, `Failed to revoke dashboard access (${response.status}).`);
        }
      });
      return input.dashboardId;
    },
    onSuccess: (dashboardId) => {
      queryClient.invalidateQueries({ queryKey: orgDashboardsQueryKeys.access(organizationId, dashboardId) });
    },
  });
}

/** A flat catalog containing only connections that expose launchable MCP Apps. */
export function useConnectionMcpAppCatalog(connections: Array<{ id: string; name: string }>) {
  const { orgContext } = useOrgDashboard();
  const organizationId = orgContext?.organization.id ?? "";
  return useQueries({
    queries: connections.map((connection) => ({
      enabled: Boolean(organizationId),
      queryKey: orgDashboardsQueryKeys.connectionApps(organizationId, connection.id),

View on GitHub (pinned to 2b7df46e8a)

Solutions

  1. On 404, invalidate orgDashboardsQueryKeys.access and refetch — the grant is already gone; treat as success.
  2. On 401/403, re-authenticate or verify access-management permissions.
  3. On 5xx, retry after refetching; confirm whether revocation succeeded before assuming failure.
  4. Ensure grantId is a current, valid ID from the latest access list response.

Example fix

// before
if (response.status !== 204 && !response.ok) {
  throw getRequestError(payload, response, `Failed to revoke dashboard access (${response.status}).`);
}
// after
if (response.status === 404) return input.dashboardId; // grant already revoked
if (response.status !== 204 && !response.ok) {
  throw getRequestError(payload, response, `Failed to revoke dashboard access (${response.status}).`);
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!input.grantId || typeof input.grantId !== "string") {
  throw new Error("A valid grantId is required to revoke access.");
}

Type guard

function isGrantId(value: unknown): value is string {
  return typeof value === "string" && value.length > 0;
}

Try / catch

try {
  await revokeAccess.mutateAsync({ dashboardId, grantId });
} catch (error) {
  if (isReauthRequiredError(error)) return startReauth();
  if (error.message.includes("(404)")) return; // already revoked; refetch
  toast.error(error.message);
} finally {
  await queryClient.invalidateQueries({ queryKey: orgDashboardsQueryKeys.access(organizationId, dashboardId) });
}

Prevention

When it happens

Trigger: Revoking a grant that was already removed (404 — e.g. two admins revoking simultaneously), missing permission to manage access (403), expired session (401), malformed grantId, or server error during revocation.

Common situations: The access list is stale and the grant was already revoked elsewhere; the UI kept an old grantId after a refetch raced with the mutation.

Related errors


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