mastra-ai/mastra · error

Unsupported Factory stage: ${stage}

Error message

Unsupported Factory stage: ${stage}

What it means

requireFactoryStage validates that a user-supplied stage string is one of the known FactoryRuleStage values (via isFactoryRuleStage) before a work-item transition mutation is sent. If the stage is not in the allowed union, it throws 'Unsupported Factory stage: <stage>' to prevent invalid board transitions from reaching the server.

Source

Thrown at mastracode/factory-ui/src/hooks/useWorkItems.ts:143

    },
    onError: (_err, _vars, context) => {
      if (context?.previous) queryClient.setQueryData(listKey, context.previous);
    },
    onSuccess: item => {
      patchCards(queryClient, listKey, cards => cards.map(i => (i.id === item.id ? item : i)));
    },
  });
}

type TransitionWorkItemVariables = {
  item: WorkItem;
  board: FactoryBoard;
  stage: string;
  cause?: string;
};

function requireFactoryStage(stage: string): FactoryRuleStage {
  if (!isFactoryRuleStage(stage)) throw new Error(`Unsupported Factory stage: ${stage}`);
  return stage;
}

export function useTransitionWorkItemMutation(factoryProjectId: string | undefined) {
  const { baseUrl } = useApiConfig();
  const queryClient = useQueryClient();
  const listKey = queryKeys.workItems(factoryProjectId);
  const mutationKey = ['factory', 'transition-work-item', factoryProjectId] as const;
  const mutation = useMutation({
    mutationKey,
    mutationFn: ({ item, board, stage, cause = 'board_drag' }: TransitionWorkItemVariables) =>
      transitionWorkItem(baseUrl, requireFactoryProjectId(factoryProjectId), item.id, {
        board,
        stage: requireFactoryStage(stage),
        expectedRevision: item.revision,
        requestId: crypto.randomUUID(),
        cause,
      }),

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Print/inspect the exact stage value in the error and compare it to the FactoryRuleStage union; correct the caller to use a valid stage.
  2. Update the isFactoryRuleStage guard / stage type union if a new legitimate stage was added server-side.
  3. Constrain the transition UI to a fixed list of valid stages instead of accepting arbitrary strings.
  4. Add a pre-submit validation mapping unknown stages to their canonical equivalents before calling the mutation.

Example fix

// before
await transition.mutateAsync({ workItemId, stage: column.id }); // column.id may be arbitrary

// after
if (!isFactoryRuleStage(column.id)) {
  toast.error(`Column '${column.id}' is not a valid Factory stage`);
  return;
}
await transition.mutateAsync({ workItemId, stage: column.id });
Defensive patterns

Strategy: validation

Validate before calling

if (!isFactoryRuleStage(stage)) {
  toast.error(`Unsupported stage: ${stage}`);
  return;
}

Type guard

const FACTORY_STAGES = ['backlog','todo','in_progress','review','done'] as const;
type FactoryRuleStage = typeof FACTORY_STAGES[number];
function isFactoryRuleStage(s: string): s is FactoryRuleStage {
  return (FACTORY_STAGES as readonly string[]).includes(s);
}

Try / catch

try {
  await transition.mutateAsync({ workItemId, stage });
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Unsupported Factory stage')) {
    toast.error(e.message);
  } else throw e;
}

Prevention

When it happens

Trigger: Calling the mutation returned by useTransitionWorkItemMutation with variables.stage set to a string that is not a FactoryRuleStage — e.g. a free-text stage from a dropdown, a renamed stage, a typo like 'in-progres', or a stage from a different board's configuration.

Common situations: Board stages were customized/renamed on the server but the UI's stage union is stale; dragging a card to a column whose id is not a canonical stage; persisted user preferences referencing an old stage name after a version upgrade.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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