{"record":{"id":"a06ba5e358fc990b","repo":"mastra-ai/mastra","slug":"connect-a-repository-before-deleting-a-workspace","errorCode":null,"errorMessage":"Connect a repository before deleting a workspace","messagePattern":"Connect a repository before deleting a workspace","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory-ui/src/hooks/useWorkspaces.ts","lineNumber":219,"sourceCode":"  });\n}\n\nexport function useDeleteWorkspaceMutation(\n  factoryId: string | undefined,\n  projectRepositoryId: string | undefined,\n  scope?: AgentControllerThreadsScope,\n) {\n  const { baseUrl } = useApiConfig();\n  const queryClient = useQueryClient();\n  const navigate = useNavigate();\n  // user-session routes carry the session id as :threadId (user/threads/:threadId)\n  const { sessionId, threadId } = useParams<{ sessionId?: string; threadId?: string }>();\n  const viewedSessionId = sessionId ?? threadId;\n\n  return useMutation({\n    mutationFn: async (workspace: FactoryUserSession) => {\n      if (!factoryId) throw new Error('No Factory selected');\n      if (!projectRepositoryId) throw new Error('Connect a repository before deleting a workspace');\n      await deleteUserSession(baseUrl, workspace.sessionId);\n      return workspace;\n    },\n    onSuccess: workspace => {\n      removeCachedSession(queryClient, projectRepositoryId, workspace.sessionId);\n      // The server strips the work-item refs with the row; mirror it in the cache\n      // so the board's cards drop their session links before the next poll.\n      if (factoryId) stripCachedSessionRefs(queryClient, factoryId, workspace.sessionId);\n      invalidateSessionQueries(queryClient, projectRepositoryId, scope, workspace.sessionId);\n      void queryClient.invalidateQueries({ queryKey: queryKeys.userSession(workspace.sessionId) });\n      void queryClient.invalidateQueries({\n        queryKey: queryKeys.agentControllerThreads(scope?.agentControllerId, scope?.resourceId, workspace.sessionId),\n      });\n      if (workspace.sessionId === viewedSessionId) void navigate(`/factories/${factoryId}/new`);\n      toast('Workspace deleted');\n    },\n    onError: error => toast.error(error instanceof Error ? error.message : 'Failed to delete workspace'),\n  });","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory-ui/src/hooks/useWorkspaces.ts#L201-L237","documentation":"In useDeleteWorkspaceMutation, after the factoryId guard, mutationFn throws 'Connect a repository before deleting a workspace' when projectRepositoryId is undefined. Deletion removes the server session and strips work-item refs from the cache keyed by the repository, so a known repository scope is required before the delete proceeds.","triggerScenarios":"Invoking deleteWorkspace on a project whose projectRepositoryId is undefined — repository never connected, was disconnected, or the repository lookup query failed/cleared the id.","commonSituations":"Stale workspace UI listing sessions from before a repository was disconnected; switching to a factory project without repos while cached workspaces are still visible; repository settings query error leaves projectRepositoryId null.","solutions":["Reconnect a repository to the Factory project before deleting orphaned workspaces, or clear stale sessions server-side.","Hide delete actions for workspaces whose project no longer has a repository, with an explanatory tooltip.","Verify the projectRepositoryId query succeeded; refetch repository settings before allowing deletes.","If the repository was intentionally removed, purge the affected workspaces via the server/admin path instead of the UI."],"exampleFix":"// before\nawait deleteWorkspace(workspace); // throws when projectRepositoryId undefined\n\n// after\nif (!projectRepositoryId) {\n  toast.error('Reconnect a repository to manage this workspace');\n  return;\n}\nawait deleteWorkspace(workspace);","handlingStrategy":"validation","validationCode":"if (!projectRepositoryId) {\n  toast.error('Reconnect a repository before managing workspaces');\n  return;\n}","typeGuard":"function hasRepository(id: string | undefined | null): id is string {\n  return typeof id === 'string' && id.length > 0;\n}","tryCatchPattern":"try {\n  await deleteWorkspace.mutateAsync(workspace);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Connect a repository')) {\n    toast.error(e.message);\n  } else throw e;\n}","preventionTips":["Hide delete controls when the workspace's project has no connected repository.","Refresh repository state before bulk workspace operations.","Clean up orphaned sessions through server-side tooling when repos are removed."],"tags":["prerequisite","configuration","factory-ui","react-query"],"backgroundTag":"missing-prerequisite-configuration","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}