mastra-ai/mastra · error
No Factory selected
Error message
No Factory selected
What it means
requireFactoryProjectId is a guard helper in the Factory UI work-items hooks. It throws 'No Factory selected' whenever the factoryProjectId argument is undefined, refusing to issue work-item API calls (create/update/transition) against an unspecified Factory board. The guard exists so mutations fail fast client-side instead of hitting the server with an ambiguous or malformed URL.
Source
Thrown at mastracode/factory-ui/src/hooks/useWorkItems.ts:31
import { useApiConfig } from '../api/config';
import { queryKeys } from '../api/keys';
import {
createWorkItem,
deleteWorkItem,
listWorkItems,
transitionWorkItem,
updateWorkItem,
} from '../ui/domains/factory/services/workItems';
import type {
BoardSnapshot,
CreateWorkItemInput,
FactoryBoard,
UpdateWorkItemInput,
WorkItem,
} from '../ui/domains/factory/services/workItems';
function requireFactoryProjectId(factoryProjectId: string | undefined): string {
if (!factoryProjectId) throw new Error('No Factory selected');
return factoryProjectId;
}
/** Rewrite the cached board's cards, keeping the run activity read alongside them. */
function patchCards(queryClient: QueryClient, listKey: QueryKey, patch: (cards: WorkItem[]) => WorkItem[]) {
// Returning undefined skips the write: never seed a partial board before the list query loads.
queryClient.setQueryData<BoardSnapshot>(listKey, board =>
board ? { runningSessionIds: board.runningSessionIds, workItems: patch(board.workItems) } : undefined,
);
}
/** Drop every card ref to a deleted session so the board stops advertising it before the next poll. */
export function stripCachedSessionRefs(queryClient: QueryClient, factoryProjectId: string, sessionId: string) {
// an in-flight list fetch still carries the stale refs and would clobber the edit below
void queryClient.cancelQueries({ queryKey: queryKeys.workItems(factoryProjectId) });
patchCards(queryClient, queryKeys.workItems(factoryProjectId), cards =>
cards.map(card => {
const kept = Object.entries(card.sessions).filter(([, ref]) => ref.sessionId !== sessionId);View on GitHub (pinned to 75dd419e61)
Solutions
- Ensure the component using the hook is rendered under the Factory project route so useParams supplies factoryProjectId.
- Gate rendering: only mount the mutation UI when factoryProjectId is truthy (e.g. if (!factoryProjectId) return <FactoryPicker/>).
- Pass the hook a guaranteed id: const projectId = factoryProjectId ?? localStorageFactoryProjectId before calling the mutation.
- Surface a 'select a Factory' prompt instead of showing mutation buttons when the id is missing.
Example fix
// before
const upsert = useUpsertWorkItemMutation(factoryProjectId);
await upsert.mutateAsync(input); // throws 'No Factory selected' if undefined
// after
if (!factoryProjectId) {
showFactoryPicker();
return;
}
const upsert = useUpsertWorkItemMutation(factoryProjectId);
await upsert.mutateAsync(input); Defensive patterns
Strategy: validation
Validate before calling
if (typeof factoryProjectId !== 'string' || factoryProjectId.length === 0) {
// render factory picker / abort before calling the mutation
} Type guard
function hasFactoryProjectId(id: string | undefined | null): id is string {
return typeof id === 'string' && id.length > 0;
} Try / catch
try {
await upsert.mutateAsync(input);
} catch (e) {
if (e instanceof Error && e.message === 'No Factory selected') {
openFactoryPicker();
} else throw e;
} Prevention
- Only render factory-scoped mutation UI inside the route that supplies factoryProjectId.
- Disable submit actions until required ids are truthy.
- Centralize id extraction from route params in one guarded helper.
When it happens
Trigger: Calling useUpsertWorkItemMutation (or any hook that internally calls requireFactoryProjectId) with factoryProjectId === undefined, then invoking the returned mutation. Typically happens when the route param ':factoryProjectId' is missing, the query is still loading, or the hook was rendered outside the Factory project route.
Common situations: Deep-linking to a work-item page without the project id in the URL; rendering the work-items component before the factory/project selection resolves; copying a hook into a context where no Factory is selected (e.g. a dashboard outside /factories/:id); a refactor that made the id optional in the hook signature.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- No Factory selected
- Factory project is required
- Factory project is required
- Factory run requires a board work item
- Work item is required
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/990cdc4a781252bb.
Report an issue: GitHub.