{"record":{"id":"e0cfdd5168b73113","repo":"mastra-ai/mastra","slug":"factory-review-phase-requires-a-controller-request","errorCode":null,"errorMessage":"Factory review phase requires a controller request context.","messagePattern":"Factory review phase requires a controller request context\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mastracode/factory/src/rules/processor.ts","lineNumber":98,"sourceCode":"type ActivePhaseSnapshotBase = {\n  bindingId: string;\n  itemId: string;\n  revision: number;\n  stage: FactoryRuleStage;\n  role: string;\n  ruleSetVersion: string;\n  status: 'active';\n};\n\ntype ActivePhaseSnapshotValue =\n  | (ActivePhaseSnapshotBase & { board: 'work' })\n  | (ActivePhaseSnapshotBase & { board: 'review' } & RuntimeSnapshot);\n\ntype PhaseSnapshotValue = ActivePhaseSnapshotValue | { bindingId?: string; status: 'none' };\n\nfunction reviewRuntimeFromRequestContext(requestContext: ComputeStateSignalArgs['requestContext']): RuntimeSnapshot {\n  if (!requestContext || typeof requestContext.get !== 'function') {\n    throw new Error('Factory review phase requires a controller request context.');\n  }\n  const context = requestContext.get<'controller', AgentControllerRequestContext<MastraCodeState>>('controller');\n  const modelId = context?.session?.modelId.trim();\n  if (!modelId) {\n    throw new Error('Factory review phase requires a selected session model.');\n  }\n  return { modelId, thinkingLevel: resolveRequestThinkingLevel(context) };\n}\n\nfunction workItemSourceKey(item: WorkItemRow): string | null {\n  const source = item.externalSource;\n  return source ? `${source.integrationId}:${source.type}:${source.externalId}` : null;\n}\n\nfunction boardForItem(item: WorkItemRow): FactoryRuleBoard {\n  return item.externalSource?.type === 'pull-request' ? 'review' : 'work';\n}\n","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/mastracode/factory/src/rules/processor.ts#L80-L116","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: calling the state computer without a request context\nconst snapshot = await computeState({ args: { ...args, requestContext: undefined } });\n// after: pass the controller request context\nconst requestContext = new RequestContext();\nrequestContext.set('controller', controllerContext);\nconst snapshot = await computeState({ args: { ...args, requestContext } });","handlingStrategy":"validation","validationCode":"if (!requestContext || typeof requestContext.get !== 'function') {\n  throw new Error('review phase requires a controller request context');\n}\nconst ctx = requestContext.get('controller');\nif (!ctx) throw new Error('controller context not set on request context');","typeGuard":"function hasRequestContext(rc) {\n  return !!rc && typeof rc.get === 'function';\n}","tryCatchPattern":"try {\n  const snapshot = reviewRuntimeFromRequestContext(requestContext);\n} catch (e) {\n  if (String(e?.message).includes('requires a controller request context')) {\n    // build and attach the RequestContext before retrying\n    const rc = new RequestContext();\n    rc.set('controller', controllerContext);\n    return reviewRuntimeFromRequestContext(rc);\n  } else throw e;\n}","preventionTips":["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"],"tags":["factory","request-context","review-phase","api-misuse"],"backgroundTag":"missing-request-context","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}