different-ai/openwork · error
Failed to load plugin access (${response.status}).
Error message
Failed to load plugin access (${response.status}). What it means
usePluginAccess fetches GET /v1/plugins/:id/access from the Den API. When the HTTP response status is not 2xx it throws this error, preferring a server-provided message extracted from the error payload via getErrorMessage, with the status-embedded fallback string if the payload has no usable message. It surfaces through TanStack Query as the query's error.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/plugin-access-data.tsx:90
role,
createdByOrgMembershipId,
createdAt,
removedAt,
};
}
export function usePluginAccess(pluginId: string) {
return useQuery({
enabled: Boolean(pluginId),
queryKey: pluginAccessQueryKeys.detail(pluginId),
queryFn: async (): Promise<PluginAccessGrant[]> => {
const { response, payload } = await requestJson(
`/v1/plugins/${encodeURIComponent(pluginId)}/access`,
{ method: "GET" },
15000,
);
if (!response.ok) {
throw new Error(getErrorMessage(payload, `Failed to load plugin access (${response.status}).`));
}
const items = isRecord(payload) && Array.isArray(payload.items) ? payload.items : [];
return items
.map(parsePluginAccessGrant)
.filter((grant): grant is PluginAccessGrant => grant !== null && grant.removedAt === null);
},
});
}
type GrantPluginAccessBody =
| { orgMembershipId: string; teamId?: never; orgWide?: never; role: PluginAccessRole }
| { orgMembershipId?: never; teamId: string; orgWide?: never; role: PluginAccessRole }
| { orgMembershipId?: never; teamId?: never; orgWide: true; role: PluginAccessRole };
export function useGrantPluginAccess() {
const queryClient = useQueryClient();
const { runReauthableAction } = useOrgDashboard();
View on GitHub (pinned to 2b7df46e8a)
Solutions
- Sign in again / refresh the session to clear 401/403, then reload the dashboard page.
- Verify the pluginId is valid for the current org by loading /v1/plugins/{id} directly (curl or browser devtools network tab).
- Confirm the Den server version supports the plugin access endpoint; upgrade the self-hosted server if 404/405 persists.
- Check Den server logs for 5xx causes (DB connectivity, migration lag) if the status is 500/502/503.
Example fix
// before: raw queryFn throwing with opaque fallback
throw new Error(getErrorMessage(payload, `Failed to load plugin access (${response.status}).`));
// after: handle 401 by re-authenticating instead of throwing
if (response.status === 401) {
await redirectToSignIn();
return [];
}
if (!response.ok) {
throw new Error(getErrorMessage(payload, `Failed to load plugin access (${response.status}).`));
} Defensive patterns
Strategy: try-catch
Validate before calling
const pluginIdOk = typeof pluginId === "string" && pluginId.length > 0;
const sessionOk = document.cookie.includes("den-session") || Boolean(await getSession());
if (!pluginIdOk || !sessionOk) { await redirectToSignIn(); } Type guard
function hasUsableErrorPayload(p: unknown): p is { message: string } {
return typeof p === "object" && p !== null && typeof (p as { message?: unknown }).message === "string";
} Try / catch
try {
const access = await pluginAccessQuery(pluginId);
} catch (err) {
const status = /\((\d{3})\)\.$/.exec(err instanceof Error ? err.message : "")?.[1];
if (status === "401") { await redirectToSignIn(); }
else if (status === "404") { showNotFound(pluginId); }
else { showToast(`Could not load plugin access${status ? ` (${status})` : ""}; retry later.`); }
} Prevention
- Check session validity before org-scoped Den API calls and redirect to sign-in on 401.
- Validate pluginId is a non-empty string before building the request URL.
- Render the access section with an empty/error state so one failed query doesn't blank the dashboard.
- Configure TanStack Query retry only for transient statuses (5xx/timeout), not 401/403/404.
When it happens
Trigger: The GET /v1/plugins/{pluginId}/access request returns 401/403 (missing or expired session, no org membership), 404 (pluginId does not exist or is not visible to the caller), 5xx (Den server/DB failure), or a network-level failure yields an error status from requestJson.
Common situations: An expired Den session cookie after idle timeout; a plugin removed by an org admin while a dashboard tab is still open; pointing den-web at a server that lacks the plugin access endpoint (version mismatch); an org slug/plugin id pasted from another org.
Related errors
- Failed to load plugin (${pluginResult.response.status}).
- Failed to load plugin contents (${membershipsResult.response
- Failed to load plugins (${response.status}).
- This install link returned incomplete setup details.
- Failed to load organizations.
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/3d1084aa5fb89419.
Report an issue: GitHub.