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

  1. 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).
  2. Use the non-throwing getId()/has-thread check and handle the null case instead of requireId().
  3. 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

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


AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30). Data as JSON: /api/errors/7008dc034f40f48a. Report an issue: GitHub.