mastra-ai/mastra · error

Factory review phase requires a selected session model.

Error message

Factory review phase requires a selected session model.

What it means

The review phase needs a concrete modelId to run the review generation, read from the controller session (context.session.modelId). If the controller context exists but no model was selected for the session (empty or whitespace-only modelId), the library throws rather than guessing a model, because review output depends on the session's chosen model and thinking level.

Source

Thrown at mastracode/factory/src/rules/processor.ts:103

  role: string;
  ruleSetVersion: string;
  status: 'active';
};

type ActivePhaseSnapshotValue =
  | (ActivePhaseSnapshotBase & { board: 'work' })
  | (ActivePhaseSnapshotBase & { board: 'review' } & RuntimeSnapshot);

type PhaseSnapshotValue = ActivePhaseSnapshotValue | { bindingId?: string; status: 'none' };

function reviewRuntimeFromRequestContext(requestContext: ComputeStateSignalArgs['requestContext']): RuntimeSnapshot {
  if (!requestContext || typeof requestContext.get !== 'function') {
    throw new Error('Factory review phase requires a controller request context.');
  }
  const context = requestContext.get<'controller', AgentControllerRequestContext<MastraCodeState>>('controller');
  const modelId = context?.session?.modelId.trim();
  if (!modelId) {
    throw new Error('Factory review phase requires a selected session model.');
  }
  return { modelId, thinkingLevel: resolveRequestThinkingLevel(context) };
}

function workItemSourceKey(item: WorkItemRow): string | null {
  const source = item.externalSource;
  return source ? `${source.integrationId}:${source.type}:${source.externalId}` : null;
}

function boardForItem(item: WorkItemRow): FactoryRuleBoard {
  return item.externalSource?.type === 'pull-request' ? 'review' : 'work';
}

function boundedError(value: unknown): FactoryRuleJsonValue {
  const message = value instanceof Error ? value.message : typeof value === 'string' ? value : 'Tool execution failed.';
  return { message: message.slice(0, 2_000) };
}

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Set a model on the controller session (session.modelId) before entering the review phase.
  2. Configure a default model for sessions so modelId is always populated.
  3. Check client wiring so the model selection is committed to session state before review is triggered.
  4. For old persisted sessions, backfill session.modelId or recreate the session.

Example fix

// before: review triggered on a session with no model
await startReviewPhase({ sessionId }); // session.modelId === ''
// after: select model first
await controller.selectModel({ sessionId, modelId: 'openai/gpt-4o' });
await startReviewPhase({ sessionId });
Defensive patterns

Strategy: validation

Validate before calling

const ctx = requestContext.get('controller');
const modelId = ctx?.session?.modelId?.trim();
if (!modelId) throw new Error('select a session model before entering the review phase');

Type guard

function hasSelectedModel(rc) {
  const ctx = rc?.get?.('controller');
  return typeof ctx?.session?.modelId === 'string' && ctx.session.modelId.trim().length > 0;
}

Try / catch

try {
  const snapshot = reviewRuntimeFromRequestContext(requestContext);
} catch (e) {
  if (String(e?.message).includes('requires a selected session model')) {
    await selectDefaultModel(controllerSession); // apply org default before retry
    return reviewRuntimeFromRequestContext(requestContext);
  } else throw e;
}

Prevention

When it happens

Trigger: The agent controller session was created without a model selection (session.modelId empty/whitespace) when the review phase's runtime snapshot was computed — e.g. session initialized lazily before the client picked a model, or the model was cleared.

Common situations: Client never sent a model selection before triggering review; default-model configuration missing on the session; session state persisted before the modelId field existed (schema migration); UI flows that start review before model setup completes.

Related errors


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