mastra-ai/mastra · error · Error
Turn not started — call start() first
Error message
Turn not started — call start() first
What it means
Turn.record is a cached memory record that is only created during start(). Accessing record before start() means the turn has no loaded record, so the getter throws to enforce the start() -> use lifecycle.
Source
Thrown at packages/memory/src/processors/observational-memory/observation-turn/turn.ts:114
this.threadId = opts.threadId;
this.resourceId = opts.resourceId;
this.messageList = opts.messageList;
this.agent = opts.agent;
this.sendSignal = opts.sendSignal;
this.sendStateSignal = opts.sendStateSignal;
this.requestContext = opts.requestContext;
this.observabilityContext = opts.observabilityContext;
this.hooks = opts.hooks ?? {};
}
readonly om: ObservationalMemory;
readonly threadId: string;
readonly resourceId: string | undefined;
readonly messageList: MessageList;
/** The current cached record. Refreshed after mutations (activate/observe/reflect). */
get record(): ObservationalMemoryRecord {
if (!this._record) throw new Error('Turn not started — call start() first');
return this._record;
}
/** The context loaded during start(). */
get context(): TurnContext {
if (!this._context) throw new Error('Turn not started — call start() first');
return this._context;
}
/** The current step, if one exists. */
get currentStep(): ObservationStep | undefined {
return this._currentStep;
}
addHooks(hooks?: ObservationTurnHooks): void {
if (!hooks) return;
Object.assign(this.hooks, hooks);
}View on GitHub (pinned to 75dd419e61)
Solutions
- Call `await turn.start(memory, runState)` before reading turn.record
- Check the private _started flag / restructure so record access happens in code paths after start()
- If you only need the record outside a turn, call om.getOrCreateRecord(threadId, resourceId) directly
Example fix
// before const turn = new ObservationTurn(om, threadId, resourceId, messageList); console.log(turn.record); // throws // after const turn = new ObservationTurn(om, threadId, resourceId, messageList); await turn.start(); console.log(turn.record); // ok
Defensive patterns
Strategy: type-guard
Validate before calling
// only access record after start() has resolved await turn.start(memory); const rec = turn.record;
Type guard
// ObservationTurn exposes no public started flag; gate by tracking start yourself
let started = false;
function turnStarted(t: ObservationTurn): boolean { return started; }
// set started = true after `await turn.start(...)` resolves Try / catch
let record: ObservationalMemoryRecord;
try {
record = turn.record;
} catch (e) {
if (e instanceof Error && e.message.includes('Turn not started')) {
await turn.start();
record = turn.record;
} else throw e;
} Prevention
- Always await turn.start() immediately after constructing a turn
- Read record only in code paths that run post-start
- Use the TurnContext returned by start() where possible
When it happens
Trigger: Reading `turn.record` after constructing `new ObservationTurn(...)` but before `await turn.start(...)` completes.
Common situations: Logging the record at turn setup; a consumer that inspects the record for telemetry before the turn is started; forgetting to await start() (floating promise) and reading record immediately after.
Related errors
- Step not prepared yet — call prepare() first
- No active thread on this session
- No source thread to clone
- Mode not found: ${this.#id}
- Observational memory record not found: ${id}
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/3e6437e7b6d51d87.
Report an issue: GitHub.