different-ai/openwork · error · Error
Failed to update MCP tool policy (${response.status}).
Error message
Failed to update MCP tool policy (${response.status}). What it means
Thrown by useUpdateMcpConnectionToolPolicy when the PUT/PATCH updating an MCP connection's tool policy returns a non-ok status (30000ms timeout). getRequestError prefers the server's error message, falling back to 'Failed to update MCP tool policy (<status>)'. On success the tools query is invalidated; on this throw the cached policy stays unchanged.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx:336
});
}
export function useUpdateMcpConnectionToolPolicy(connectionId: string) {
const queryClient = useQueryClient();
const { orgId } = useOrgDashboard();
return useMutation({
mutationFn: async (input: Pick<ExternalMcpToolPolicyView, "allDisabled" | "disabledTools">): Promise<ExternalMcpToolPolicyView> => {
const { response, payload } = await requestJson(
`/v1/mcp-connections/${encodeURIComponent(connectionId)}/tool-policy`,
{
method: "PUT",
headers: getOrgScopeHeaders(requireOrgId(orgId)),
body: JSON.stringify(input),
},
30000,
);
if (!response.ok) {
throw getRequestError(payload, response, `Failed to update MCP tool policy (${response.status}).`);
}
const policy = isRecord(payload) ? parseExternalMcpToolPolicy(payload.policy) : null;
if (!policy) throw new Error("MCP tool policy response was incomplete.");
return policy;
},
onSuccess: () => queryClient.invalidateQueries({ queryKey: mcpConnectionQueryKeys.tools(orgId, connectionId) }),
});
}
// The den-api tool run is bounded by its 150s MCP tool lifecycle deadline;
// give the request a little headroom so the server's structured failure
// arrives instead of a client-side timeout.
const RUN_TOOL_REQUEST_TIMEOUT_MS = 160000;
export function useRunMcpConnectionTool(connectionId: string) {
const { orgId } = useOrgDashboard();
return useMutation({
mutationFn: async (input: { toolName: string; arguments: Record<string, unknown> }): Promise<ExternalMcpToolRun> => {View on GitHub (pinned to 2b7df46e8a)
Solutions
- For 400/422, re-fetch the tool catalog first and rebuild the policy from the current tool list.
- For 403, obtain org admin/connection-admin permission or adjust org policy.
- For 404, refresh the connections list and reopen the settings for the correct connection.
- For 401, re-authenticate; handle isReauthRequiredError explicitly.
- For 5xx, retry with backoff and check server logs.
Example fix
// before
await updatePolicy(input);
// after
try {
await updatePolicy(input);
} catch (err) {
if (isReauthRequiredError(err)) { startReauth(); }
else if (/\((400|422)\)/.test(err.message)) { await refetchTools(); rebuildPolicyFromCatalog(); }
else showError(err.message);
} Defensive patterns
Strategy: validation
Validate before calling
// validate the policy against the current catalog before submitting
const known = new Set(tools.map(t => t.name));
const invalid = Object.keys(input).filter(name => !known.has(name));
if (invalid.length) throw new Error(`Unknown tools in policy: ${invalid.join(", ")}`); Type guard
function isValidationError(err: unknown): boolean {
return err instanceof Error && /\((400|422)\)/.test(err.message);
} Try / catch
try {
await updatePolicy(input);
} catch (err) {
if (isReauthRequiredError(err)) startReauth();
else if (isValidationError(err)) { await refetchTools(); }
else showError(err.message);
} Prevention
- Rebuild policies from a freshly fetched tool catalog, never from stale UI state
- Confirm the connection still exists before editing its policy
- Require connection-admin role before exposing policy editing
- Invalidate the tools query after updates so subsequent edits use fresh data
When it happens
Trigger: Non-ok response from the tool-policy endpoint with the submitted policy body: 400/422 when the policy payload fails server validation (unknown tool names, bad allow/deny shape), 403 when org policy forbids editing tool permissions, 404 when the connection no longer exists, 401 for expired sessions, 5xx server faults.
Common situations: Editing policy for a connection that was deleted in another tab (stale id); submitting a policy referencing tools the server no longer lists; session expiry; role without connection-admin rights.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- Failed to configure plugin connection (${response.status}).
- Failed to inspect MCP tools (${response.status}).
- Failed to load MCP connectors (${response.status}).
- Failed to load MCP presets (${response.status}).
- Failed to look up the MCP server (${response.status}).
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/887236f9874a2f87.
Report an issue: GitHub.