{"record":{"id":"f1b6714e929f1f43","repo":"different-ai/openwork","slug":"disconnect-mcp-connection-response-was-incomplete","errorCode":null,"errorMessage":"Disconnect MCP connection response was incomplete.","messagePattern":"Disconnect MCP connection response was incomplete\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx","lineNumber":945,"sourceCode":"export function useDisconnectMcpConnection() {\n  const queryClient = useQueryClient();\n  const { orgId, runReauthableAction } = useOrgDashboard();\n\n  return useMutation({\n    mutationFn: async (connectionId: string): Promise<string> => {\n      let result: string | null = null;\n      await runReauthableAction(\"disconnect-mcp-connection\", async () => {\n        const { response, payload } = await requestJson(\n          `/v1/mcp-connections/${encodeURIComponent(connectionId)}/disconnect`,\n          { method: \"POST\", headers: getOrgScopeHeaders(requireOrgId(orgId)) },\n          15000,\n        );\n        if (!response.ok) {\n          throw getRequestError(payload, response, `Failed to disconnect MCP connection (${response.status}).`);\n        }\n        result = connectionId;\n      });\n      if (!result) throw new Error(\"Disconnect MCP connection response was incomplete.\");\n      return result;\n    },\n    onSuccess: () => {\n      queryClient.invalidateQueries({ queryKey: mcpConnectionQueryKeys.all });\n    },\n  });\n}\n\nexport function useDeleteMcpConnection() {\n  const queryClient = useQueryClient();\n  const { orgId, runReauthableAction } = useOrgDashboard();\n\n  return useMutation({\n    mutationFn: async (connectionId: string): Promise<string> => {\n      let result: string | null = null;\n      await runReauthableAction(\"delete-mcp-connection\", async () => {\n        const { response, payload } = await requestJson(\n          `/v1/mcp-connections/${encodeURIComponent(connectionId)}`,","sourceCodeStart":927,"sourceCodeEnd":963,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx#L927-L963","documentation":"The disconnect MCP connection mutation assigns `result = connectionId` inside runReauthableAction after a successful disconnect fetch. If the callback never assigned (re-auth resolved without executing, or connectionId was falsy) this guard throws so the mutation can't resolve with undefined.","triggerScenarios":"mutateAsync disconnect with an empty/undefined connectionId, or runReauthableAction resolving without running the callback because re-auth was dismissed or its contract changed.","commonSituations":"Disconnect clicked on a row whose connection was already removed server-side and locally refetched away; expired Den session with cancelled re-auth; refactor changed the wrapper's return behavior.","solutions":["Ensure connectionId is a non-empty string before mutating","Verify runReauthableAction throws on dismissed re-auth rather than resolving undefined","Log inside the callback to confirm the disconnect fetch and assignment execute","Note the disconnect endpoint may return 2xx with empty body — the guard only checks the local variable, so confirm the callback reached `result = connectionId`"],"exampleFix":"// before\nif (!result) throw new Error(\"Disconnect MCP connection response was incomplete.\");\n// after\nif (!result) {\n  throw new Error(`Disconnect MCP connection: no connectionId assigned (input=${JSON.stringify(connectionId)}).`);\n}","handlingStrategy":"validation","validationCode":"if (typeof connectionId !== 'string' || connectionId.length === 0) {\n  throw new Error('cannot disconnect: connectionId missing');\n}","typeGuard":"function isDisconnectInput(v: unknown): v is { connectionId: string } {\n  return isRecord(v) && typeof v.connectionId === 'string' && v.connectionId.length > 0;\n}","tryCatchPattern":"try {\n  await disconnect.mutateAsync(connectionId);\n} catch (e) {\n  showToast({ variant: 'error', title: 'Disconnect failed', description: e instanceof Error ? e.message : String(e) });\n  queryClient.invalidateQueries({ queryKey: mcpConnectionQueryKeys.all });\n}","preventionTips":["Guard disconnect buttons against stale/already-removed rows","Invalidate the list on error to reconcile UI with server state","Keep the reauth wrapper throwing on dismissal","Add an API test that the disconnect endpoint responds 2xx with a JSON body"],"tags":["react-query","mutation","null-guard"],"backgroundTag":"empty-api-response","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}