{"record":{"id":"9ff32bba526421ed","repo":"mastra-ai/mastra","slug":"step-not-prepared-yet-call-prepare-first","errorCode":null,"errorMessage":"Step not prepared yet — call prepare() first","messagePattern":"Step not prepared yet — call prepare\\(\\) first","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/memory/src/processors/observational-memory/observation-turn/step.ts","lineNumber":54,"sourceCode":"    return this._prepared;\n  }\n\n  /**\n   * Serialize to a minimal, acyclic snapshot.\n   *\n   * The `turn` back-reference exists only so a step can read context off its parent turn at\n   * runtime. It closes the `ObservationTurn._currentStep -> ObservationStep.turn` cycle, so\n   * serializing it throws \"Converting circular structure to JSON\" (e.g. when a turn is stashed\n   * in processor state that flows into a processor-workflow snapshot). The parent turn fully\n   * owns the step, so omitting the back-reference is lossless.\n   */\n  toJSON() {\n    return { stepNumber: this.stepNumber, prepared: this._prepared };\n  }\n\n  /** Step context from prepare(). Throws if prepare() hasn't been called. */\n  get context(): StepContext {\n    if (!this._context) throw new Error('Step not prepared yet — call prepare() first');\n    return this._context;\n  }\n\n  /**\n   * Prepare this step for agent generation.\n   *\n   * For step 0: activates buffered chunks, checks reflection, builds system message, filters observed.\n   * For step > 0: checks thresholds, triggers buffer/observe, saves previous messages,\n   * builds system message, filters observed.\n   */\n  async prepare(): Promise<StepContext> {\n    if (this._prepared) throw new Error(`Step ${this.stepNumber} already prepared`);\n\n    const { threadId, resourceId, messageList } = this.turn;\n    // Cast to any for internal access to private OM methods (Turn/Step are internal consumers)\n    const om = this.turn.om;\n    let activated = false;\n    let observed = false;","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/mastra-ai/mastra/blob/75dd419e613fe9c39f846ffc500716141b74fda6/packages/memory/src/processors/observational-memory/observation-turn/step.ts#L36-L72","documentation":"ObservationStep lazily holds a StepContext that only exists after prepare() has run. The `context` getter is a fail-fast accessor: if you read it before calling prepare(), there is nothing to return, so it throws telling you the required call order.","triggerScenarios":"Accessing `step.context` (or indirectly via code that reads the step context) before `await step.prepare()` has completed for that step instance.","commonSituations":"Calling context in a derived getter/log statement before generation; forgetting to await prepare() (floating promise); reusing an old step object from a previous turn whose prepare was never invoked.","solutions":["Call `await step.prepare()` before reading `step.context`","Check `step.toJSON().prepared` (or wrap access) if you need to read context conditionally","Ensure prepare()'s promise is awaited — an unawaited prepare means context is still undefined when read"],"exampleFix":"// before\nconst step = turn.step(0);\nconsole.log(step.context); // throws\n// after\nconst step = turn.step(0);\nconst ctx = await step.prepare();\nconsole.log(step.context); // ok","handlingStrategy":"try-catch","validationCode":"// guard via the step's own state before access\nif (!step.toJSON().prepared) await step.prepare();\nconst ctx = step.context;","typeGuard":"function isStepPrepared(step: ObservationStep): boolean {\n  return step.toJSON().prepared;\n}","tryCatchPattern":"let ctx: StepContext;\ntry {\n  ctx = step.context;\n} catch (e) {\n  if (e instanceof Error && e.message.includes('not prepared yet')) {\n    ctx = await step.prepare();\n  } else throw e;\n}","preventionTips":["Always await step.prepare() before reading context","Never log/inspect step.context in pre-prepare code paths","Track prepare() calls to avoid floating promises"],"tags":["observational-memory","lifecycle","state"],"backgroundTag":"method-called-out-of-order","analyzedSha":"75dd419e613fe9c39f846ffc500716141b74fda6","analyzedAt":"2026-08-30T00:15:31.844Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}