mastra-ai/mastra · error
Factory review phase requires a controller request context.
Error message
Factory review phase requires a controller request context.
What it means
reviewRuntimeFromRequestContext builds the runtime snapshot for the Factory review phase from the incoming request context. Wake/kickoff dispatch must run under a controller request context that carries the agent controller session; if requestContext is missing or lacks a .get function, the library cannot resolve the controller session, so it throws before any model work begins. Callers (e.g. the 'value' state computer) must supply the server request context.
Solutions
- Invoke the review phase only through the agent request path that provides RequestContext, and set the 'controller' entry on it.
- In tests/background jobs, construct and pass a real RequestContext (requestContext.set('controller', ...)) instead of undefined.
- Check the call site populating ComputeStateSignalArgs.requestContext and restore propagation if it was dropped.
- Ensure any context adapter/wrapper still exposes the .get method expected by the processor.
Example fix
// before: calling the state computer without a request context
const snapshot = await computeState({ args: { ...args, requestContext: undefined } });
// after: pass the controller request context
const requestContext = new RequestContext();
requestContext.set('controller', controllerContext);
const snapshot = await computeState({ args: { ...args, requestContext } }); Defensive patterns
Strategy: validation
Validate before calling
if (!requestContext || typeof requestContext.get !== 'function') {
throw new Error('review phase requires a controller request context');
}
const ctx = requestContext.get('controller');
if (!ctx) throw new Error('controller context not set on request context'); Type guard
function hasRequestContext(rc) {
return !!rc && typeof rc.get === 'function';
} Try / catch
try {
const snapshot = reviewRuntimeFromRequestContext(requestContext);
} catch (e) {
if (String(e?.message).includes('requires a controller request context')) {
// build and attach the RequestContext before retrying
const rc = new RequestContext();
rc.set('controller', controllerContext);
return reviewRuntimeFromRequestContext(rc);
} else throw e;
} Prevention
- Only invoke review-phase compute paths from the agent request pipeline that supplies RequestContext
- In tests, construct a real RequestContext with the controller entry instead of stubs
- Keep ComputeStateSignalArgs.requestContext propagation intact through wrappers/adapters
- Add an early assert for requestContext presence at API boundaries
When it happens
Trigger: The review-phase processor was invoked without a requestContext at all, or with an object that isn't a RequestContext (no .get method) — e.g. calling the compute-state 'value' signal directly, from a background job, or in a test with a bare context.
Common situations: Invoking the review processor from scripts/tests without constructing RequestContext; wiring the processor into a path that doesn't propagate the HTTP request context; refactors that changed the context shape passed to ComputeStateSignalArgs.
Related errors
- Factory review phase requires a selected session model.
- AGENT_DURABLE_METHOD_NOT_AVAILABLE
- AGENT_REQUEST_CONTEXT_VALIDATION_FAILED
- All message IDs must be non-empty strings
- Bound Factory work item not found.
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/e0cfdd5168b73113.
Report an issue: GitHub.
Appendix: source
Thrown at mastracode/factory/src/rules/processor.ts:98
type ActivePhaseSnapshotBase = {
bindingId: string;
itemId: string;
revision: number;
stage: FactoryRuleStage;
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';
}
View on GitHub (pinned to 75dd419e61)