mastra-ai/mastra · error

Factory runs require one exclusive destination stage

Error message

Factory runs require one exclusive destination stage

What it means

useStartFactoryRun derives the destination stage as `workItem.stages.length === 1 ? workItem.stages[0] : undefined` and then validates it with isFactoryRuleStage(desiredStage). Factory runs must target exactly one recognized rule stage; if the work item has zero, multiple, or an unrecognized stage, the mutation throws 'Factory runs require one exclusive destination stage' before calling startFactoryRun.

Source

Thrown at mastracode/factory-ui/src/hooks/useStartFactoryRun.ts:103

  const { baseUrl } = useApiConfig();
  const navigate = useNavigate();
  const queryClient = useQueryClient();
  const repository = factoryQuery.data?.repositories[0];
  const [phases, setPhases] = useState<Record<string, FactoryRunPhase>>({});

  const mutation = useMutation({
    mutationKey: factoryRunMutationKey(repository?.projectRepositoryId ?? '', factoryId),
    mutationFn: async ({ branch, threadTitle, threadTags, invocation, workItem }: StartFactoryRunInput) => {
      if (!factoryId || !workItem) throw new Error('Factory run requires a board work item');
      if (!repository) throw new Error('Select a repository before starting a Factory run');
      const phaseKey = runPhaseKey({ id: workItem.id, sourceKey: workItem.sourceKey, role: workItem.role });
      const setPhase = (phase: FactoryRunPhase) => setPhases(current => ({ ...current, [phaseKey]: phase }));

      setPhase('workspace');
      const userSession = await createUserSession(baseUrl, repository.projectRepositoryId, { branch });
      const sessionId = userSession.sessionId;
      const desiredStage = workItem.stages.length === 1 ? workItem.stages[0] : undefined;
      if (!isFactoryRuleStage(desiredStage)) throw new Error('Factory runs require one exclusive destination stage');

      setPhase('kickoff');
      const prepared = await startFactoryRun(baseUrl, factoryId, {
        sessionId,
        threadTitle,
        threadTags,
        kickoffKey: crypto.randomUUID(),
        invocation:
          invocation?.type === 'skill'
            ? {
                ...invocation,
                arguments: `${invocation.arguments.trim()}\n\nPrepared workspace context:\n- Session: ${sessionId}\n- Branch: ${userSession.branch}`,
              }
            : invocation,
        destinationStage: desiredStage,
        workItem: {
          id: workItem.id,
          role: workItem.role,

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Edit the board work item so it has exactly one destination stage that matches a valid factory rule stage.
  2. Refresh the board/work item data to clear stale stage names after a taxonomy change.
  3. Update isFactoryRuleStage (or the stage enum) if a new legitimate stage type was introduced but not added to the union.

Example fix

// before
start({ workItem }); // workItem.stages = ['review', 'deploy']

// after
const runnable = workItem.stages.length === 1 && isFactoryRuleStage(workItem.stages[0]);
if (runnable) start({ workItem });
Defensive patterns

Strategy: validation

Validate before calling

const stage = workItem?.stages.length === 1 ? workItem.stages[0] : undefined;
if (!isFactoryRuleStage(stage)) return; // block start, prompt user to fix stages

Type guard

function isFactoryRuleStage(s: unknown): s is FactoryRuleStage {
  return typeof s === 'string' && RULE_STAGES.includes(s as FactoryRuleStage);
}

Try / catch

try { await start(input); } catch (e) { if ((e as Error).message.includes('exclusive destination stage')) openStageEditor(workItem); }

Prevention

When it happens

Trigger: Starting a run for a workItem whose stages array has length != 1, or whose single stage fails the isFactoryRuleStage check (wrong/legacy stage name) — e.g. a board item configured for multiple destination stages, or stage taxonomy changed server-side.

Common situations: Work item configured in the board UI with several target stages; stale board data after a stage was renamed/removed so the item's stage string no longer matches the rule-stage union; importing work items from an integration that assigns multiple stages.

Related errors


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/bfeeb165a07a199e. Report an issue: GitHub.