{"record":{"id":"2bd4e7cc7c3e4c73","repo":"mastra-ai/mastra","slug":"select-a-repository-before-starting-a-factory-run","errorCode":null,"errorMessage":"Select a repository before starting a Factory run","messagePattern":"Select a repository before starting a Factory run","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory-ui/src/hooks/useStartFactoryRun.ts","lineNumber":95,"sourceCode":" * The coordinator commits exact authority before it dispatches any message.\n *\n * The run is started in the background: the board stays put and a toast offers\n * the way into the thread once it exists.\n */\nexport function useStartFactoryRun() {\n  const { factoryId } = useParams<{ factoryId: string }>();\n  const factoryQuery = useFactoryQuery(factoryId);\n  const { baseUrl } = useApiConfig();\n  const navigate = useNavigate();\n  const queryClient = useQueryClient();\n  const repository = factoryQuery.data?.repositories[0];\n  const [phases, setPhases] = useState<Record<string, FactoryRunPhase>>({});\n\n  const mutation = useMutation({\n    mutationKey: factoryRunMutationKey(repository?.projectRepositoryId ?? '', factoryId),\n    mutationFn: async ({ branch, threadTitle, threadTags, invocation, workItem }: StartFactoryRunInput) => {\n      if (!factoryId || !workItem) throw new Error('Factory run requires a board work item');\n      if (!repository) throw new Error('Select a repository before starting a Factory run');\n      const phaseKey = runPhaseKey({ id: workItem.id, sourceKey: workItem.sourceKey, role: workItem.role });\n      const setPhase = (phase: FactoryRunPhase) => setPhases(current => ({ ...current, [phaseKey]: phase }));\n\n      setPhase('workspace');\n      const userSession = await createUserSession(baseUrl, repository.projectRepositoryId, { branch });\n      const sessionId = userSession.sessionId;\n      const desiredStage = workItem.stages.length === 1 ? workItem.stages[0] : undefined;\n      if (!isFactoryRuleStage(desiredStage)) throw new Error('Factory runs require one exclusive destination stage');\n\n      setPhase('kickoff');\n      const prepared = await startFactoryRun(baseUrl, factoryId, {\n        sessionId,\n        threadTitle,\n        threadTags,\n        kickoffKey: crypto.randomUUID(),\n        invocation:\n          invocation?.type === 'skill'\n            ? {","sourceCodeStart":77,"sourceCodeEnd":113,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory-ui/src/hooks/useStartFactoryRun.ts#L77-L113","documentation":"Inside useStartFactoryRun, after validating factoryId/workItem, the mutation checks that a repository has been resolved from the factory query (factoryQuery.data?.repositories[0]). If no repository is selected or the factory has no repositories, it throws 'Select a repository before starting a Factory run' because createUserSession(baseUrl, repository.projectRepositoryId, ...) needs a concrete repository id.","triggerScenarios":"Calling start() when factoryQuery.data.repositories is empty or repository state hasn't been set — e.g. the factory loads with zero repositories, the repository picker was never interacted with, or the run button was clicked while factoryQuery was still fetching.","commonSituations":"New factory project with no repositories connected yet; user opened the run dialog before the factory query resolved; a filter/selection change cleared the chosen repository but the run button stayed enabled.","solutions":["Disable the start/run control until a repository is selected (repository is defined).","Connect at least one repository to the factory project, or show a 'no repositories' state instead of the run button.","Gate on factoryQuery.isSuccess so the run UI only appears after the repository list has loaded."],"exampleFix":"// before\n<button onClick={run} />\n\n// after\n<button disabled={!repository} onClick={run} />","handlingStrategy":"validation","validationCode":"if (!repository) return; // show 'select a repository' state instead","typeGuard":"const hasRepository = (r: FactoryRepository | undefined): r is FactoryRepository => Boolean(r?.projectRepositoryId);","tryCatchPattern":"try { await start(input); } catch (e) { if ((e as Error).message.includes('Select a repository')) focusRepositoryPicker(); }","preventionTips":["Disable run controls until factoryQuery succeeds and a repository is selected.","Show an explicit empty state when the factory has zero repositories.","Reset repository selection state when switching factories."],"tags":["guard-clause","state-management","factory-ui","react-query"],"backgroundTag":"missing-required-parameter","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}