mastra-ai/mastra · error
No active thread on this session
Error message
No active thread on this session
What it means
requireId() is the accessor for the session's active thread id. The library throws this when the AgentController session has never been bound to a thread (#threadId is null) and code asks for an id that does not exist. It is a deliberate fail-fast guard instead of returning a null id that callers might misuse.
Source
Thrown at packages/core/src/agent-controller/session.ts:373
throw new Error('SessionThread has not been connected to its session');
}
return this.#session;
}
/** The active thread id, or null when the session is not bound to a thread. */
getId(): string | null {
return this.#threadId;
}
/** Whether the session is currently bound to a thread. */
isSet(): boolean {
return this.#threadId !== null;
}
/** The active thread id, throwing when the session is not bound to a thread. */
requireId(): string {
if (this.#threadId === null) {
throw new Error('No active thread on this session');
}
return this.#threadId;
}
/** Bind the session to a thread. */
set({ threadId }: { threadId: string }): void {
this.#threadId = threadId;
}
/** Clear the session's thread binding. */
clear(): void {
this.#threadId = null;
}
/** Clear the session's thread binding and release its lock when one is held. */
async clearAndReleaseLock(): Promise<void> {
const threadId = this.#threadId;
this.#threadId = null;View on GitHub (pinned to 75dd419e61)
Solutions
- Create or resume a thread before reading the id (e.g. call the session bind/set path with a threadId, or select a thread via promptForThreadSelection).
- Use the non-throwing getId()/has-thread check and handle the null case instead of requireId().
- If a thread should always exist, initialize it during session construction so #threadId is set early.
Example fix
// before
const id = session.currentThreadId(); // throws when no thread
// after
const id = session.thread.getId();
if (id === null) {
await session.thread.create({ title: 'New session' });
}
const threadId = session.requireId(); Defensive patterns
Strategy: type-guard
Validate before calling
if (session.thread.getId() === null) { await session.thread.create({ title: 'New session' }); } Type guard
function hasActiveThread(s: { thread: { getId(): string | null } }): s is typeof s & { thread: { getId(): string } } {
return s.thread.getId() !== null;
} Try / catch
let threadId: string;
try {
threadId = session.requireId();
} catch (e) {
if (e instanceof Error && e.message === 'No active thread on this session') {
await session.thread.create({ title: 'New session' });
threadId = session.requireId();
} else throw e;
} Prevention
- Check getId() for null instead of calling requireId() when absence is possible
- Bind/create a thread immediately after session construction
- Gate UI actions that need a thread on the has-thread check
- Never assume sessions auto-create threads
When it happens
Trigger: Calling requireId() (directly or via the threadId/oldThreadId/aThreadId/currentThreadId accessors) before any bind/set() call, after an explicit unbind, or on a freshly constructed session with no --thread/--resume equivalent.
Common situations: Running the CLI without a resumed or created thread; reading currentThreadId in a hook that fires before thread selection; assuming a session auto-creates a thread when it defers binding until first prompt.
Related errors
- No source thread to clone
- Thread not found: ${threadId}
- Mode not found: ${this.#id}
- Cannot start a destroyed sandbox
- Step not prepared yet — call prepare() first
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/7008dc034f40f48a.
Report an issue: GitHub.