mastra-ai/mastra · error

No Factory selected

Error message

No Factory selected

What it means

useCreateWorkspaceMutation's mutationFn throws 'No Factory selected' when factoryId is undefined at the moment a workspace creation is attempted. Workspaces are always scoped to a Factory, so creating one without that context is rejected before any network call. A companion check ensures a repository is connected first.

Source

Thrown at mastracode/factory-ui/src/hooks/useWorkspaces.ts:191

  return useQuery({
    queryKey: queryKeys.userSession(sessionId),
    queryFn: sessionId ? () => getUserSession(baseUrl, sessionId) : skipToken,
  });
}

export function useCreateWorkspaceMutation(
  factoryId: string | undefined,
  projectRepositoryId: string | undefined,
  scope?: AgentControllerThreadsScope,
) {
  const { baseUrl } = useApiConfig();
  const queryClient = useQueryClient();
  const navigate = useNavigate();

  return useMutation({
    mutationFn: async (branch: string) => {
      const trimmedBranch = branch.trim();
      if (!factoryId) throw new Error('No Factory selected');
      if (!projectRepositoryId) throw new Error('Connect a repository before creating a workspace');
      return createUserSession(baseUrl, projectRepositoryId, { branch: trimmedBranch });
    },
    onSuccess: session => {
      invalidateSessionQueries(queryClient, projectRepositoryId, scope, session.sessionId);
      void queryClient.invalidateQueries({ queryKey: queryKeys.userSession(session.sessionId) });
      void navigate(`/factories/${factoryId}/workspaces/${session.sessionId}`);
    },
    onError: error => toast.error(error instanceof Error ? error.message : 'Failed to create workspace'),
  });
}

export function useDeleteWorkspaceMutation(
  factoryId: string | undefined,
  projectRepositoryId: string | undefined,
  scope?: AgentControllerThreadsScope,
) {
  const { baseUrl } = useApiConfig();

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Render the create-workspace UI only inside the /factories/:factoryId route so useParams provides factoryId.
  2. Disable the create button until factoryId is truthy and show a factory selector otherwise.
  3. If embedding elsewhere, pass factoryId explicitly to the hook instead of relying on route params.
  4. Wait for the factory query to finish loading before exposing the form.

Example fix

// before
const createWorkspace = useCreateWorkspaceMutation(factoryId, projectRepositoryId, ...);
<button onClick={() => createWorkspace.mutate(branch)} /> // throws when factoryId undefined

// after
disabled={!factoryId || !projectRepositoryId}
title={factoryId ? undefined : 'Select a Factory first'}
Defensive patterns

Strategy: validation

Validate before calling

if (!factoryId) {
  showFactoryPicker();
  return; // do not call mutation
}

Type guard

function hasFactoryId(id: string | undefined | null): id is string {
  return typeof id === 'string' && id.length > 0;
}

Try / catch

try {
  await createWorkspace.mutateAsync(branch);
} catch (e) {
  if (e instanceof Error && e.message === 'No Factory selected') {
    toast.error('Select a Factory before creating a workspace');
  } else throw e;
}

Prevention

When it happens

Trigger: Invoking the createWorkspace mutation while factoryId (from route params or factory context) is undefined — e.g. the hook rendered outside a factory route, or before the factory id resolves from the URL/query.

Common situations: Navigating to the 'new workspace' flow via a bookmarked URL missing the factory segment; the factory list still loading so no factory is selected; embedding the workspace form in a layout that lacks the FactoryId provider/route param.

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


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