{"record":{"id":"00796f3f4f46c15c","repo":"different-ai/openwork","slug":"failed-to-load-mcp-connectors-response-status","errorCode":null,"errorMessage":"Failed to load MCP connectors (${response.status}).","messagePattern":"Failed to load MCP connectors \\((.+?)\\)\\.","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx","lineNumber":558,"sourceCode":"  return Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction parseRequiredBy(value: unknown): ExternalMcpRequiredBy[] {\n  if (!Array.isArray(value)) return [];\n  return value.flatMap((entry) => {\n    if (!isRecord(entry) || typeof entry.pluginId !== \"string\" || typeof entry.name !== \"string\") return [];\n    return [{ pluginId: entry.pluginId, name: entry.name }];\n  });\n}\n\nasync function fetchConnections(scope: ExternalMcpConnectionScope, orgId: string): Promise<ExternalMcpConnection[]> {\n  const { response, payload } = await requestJson(\n    `/v1/mcp-connections?scope=${scope}`,\n    { headers: getOrgScopeHeaders(orgId) },\n    15000,\n  );\n  if (!response.ok) {\n    throw getRequestError(payload, response, `Failed to load MCP connectors (${response.status}).`);\n  }\n  const record = payload as { connections?: ExternalMcpConnection[] };\n  return (record.connections ?? []).map((connection) => ({\n    ...connection,\n    requiredBy: parseRequiredBy(connection.requiredBy),\n    identityManagedBy: parseRequiredBy(connection.identityManagedBy),\n    updatedAt: typeof connection.updatedAt === \"string\" ? connection.updatedAt : null,\n    ...(typeof connection.createdByName === \"string\" || connection.createdByName === null ? { createdByName: connection.createdByName } : {}),\n    ...(typeof connection.needsReconnect === \"boolean\" ? { needsReconnect: connection.needsReconnect } : {}),\n    ...(connection.credentialHealth === \"unknown\" || connection.credentialHealth === \"ready\" || connection.credentialHealth === \"reconnect_required\"\n      ? { credentialHealth: connection.credentialHealth }\n      : {}),\n    ...(typeof connection.issuerReviewRequired === \"boolean\" ? { issuerReviewRequired: connection.issuerReviewRequired } : {}),\n    ...(connection.reconnectActionOwner === \"member\" || connection.reconnectActionOwner === \"organization_admin\" || connection.reconnectActionOwner === null\n      ? { reconnectActionOwner: connection.reconnectActionOwner }\n      : {}),\n    ...(isStringArray(connection.missingFeatures) ? { missingFeatures: connection.missingFeatures } : {}),\n    ...(typeof connection.externalAccountId === \"string\" || connection.externalAccountId === null","sourceCodeStart":540,"sourceCodeEnd":576,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx#L540-L576","documentation":"Thrown by fetchConnections (the queryFn of useMcpConnections) when GET /v1/mcp-connections?scope=<scope> returns a non-ok status (15000ms timeout). getRequestError surfaces the server's error message or 'Failed to load MCP connectors (<status>)'. The hook then surfaces the error via TanStack Query's error state instead of returning a connection list.","triggerScenarios":"Non-ok response listing org MCP connections: 401 when the Den session expired, 403 when the org scope headers are missing/invalid or the user lacks read access, 400 for an unsupported scope value, 5xx on server faults or during Den deploys.","commonSituations":"Opening the MCP connectors page after a long idle session (expired token); switching orgs with a stale orgId header; a bad scope query parameter after a client/server version mismatch; transient Den server 5xx.","solutions":["For 401/403, re-authenticate and verify getOrgScopeHeaders receives a valid orgId.","For 400, check the scope value against the API version the server runs (client/server mismatch after upgrade).","For 5xx, retry (TanStack Query retry) with backoff and check Den server health.","In the component, branch on error state and call isReauthRequiredError to trigger re-auth instead of rendering a blank list."],"exampleFix":"// before\nconst { data: connections } = useMcpConnections(orgId, scope);\n// after\nconst { data: connections, error, refetch } = useMcpConnections(orgId, scope);\nif (error) {\n  if (isReauthRequiredError(error)) startReauth();\n  else if (isRetryable(error)) refetch();\n  else showError(error.message);\n}","handlingStrategy":"retry","validationCode":"// before querying\nif (!orgId) throw new Error(\"Select an organization to list MCP connectors\");\nconst validScopes = [\"org\", \"user\"];\nif (!validScopes.includes(scope)) throw new Error(`Unsupported scope: ${scope}`);","typeGuard":"function isRetryableListError(err: unknown): boolean {\n  return err instanceof Error && /\\((5\\d\\d|408|429)\\)/.test(err.message);\n}","tryCatchPattern":"useQuery({\n  queryKey: mcpConnectionQueryKeys.list(orgId, scope),\n  queryFn: () => fetchConnections(orgId, scope),\n  retry: (count, err) => count < 3 && isRetryableListError(err),\n});","preventionTips":["Keep the org context synchronized with the session to avoid stale scope headers","Proactively refresh sessions on 401 instead of failing the list render","Pin client and server API versions so the scope parameter stays valid","Render an explicit error state with a retry button from the query error"],"tags":["http","den-api","mcp"],"backgroundTag":"http-request-failed","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}