mastra-ai/mastra · error

No source thread to clone

Error message

No source thread to clone

What it means

clone() copies a source thread; the source defaults to the session's currently bound thread. When no explicit sourceThreadId is given and the session has no active thread (#threadId is null), there is nothing to copy and the library throws this fail-fast error.

Source

Thrown at packages/core/src/agent-controller/session.ts:696

        thread: { ...thread, title, updatedAt: new Date() },
      });
      this.#owner.emit({ type: 'thread_title_updated', threadId, title });
    }
  }

  /** Clone a thread (and its messages), bind the session to the clone, and rebind the stream. */
  async clone({
    sourceThreadId,
    title,
    resourceId,
  }: {
    sourceThreadId?: string;
    title?: string;
    resourceId?: string;
  } = {}): Promise<AgentControllerThread> {
    const sourceId = sourceThreadId ?? this.#threadId;
    if (!sourceId) {
      throw new Error('No source thread to clone');
    }
    // Only allow cloning from a source thread this session owns.
    if (this.#store?.hasStorage()) {
      await this.#requireOwnedThread({ threadId: sourceId });
    }
    return this.#cloneThread({
      sourceThreadId: sourceId,
      resourceId: resourceId ?? this.#owner.identity.getResourceId(),
      title,
    });
  }

  async #cloneThread({
    sourceThreadId,
    resourceId,
    title,
    metadata,
  }: {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Bind or create a thread first so the session has a current thread, then call clone().
  2. Pass an explicit sourceThreadId to clone({ sourceThreadId }).
  3. Guard the UI action: disable clone until the session reports it has an active thread.

Example fix

// before
const t = await session.clone(); // throws when no active thread
// after
const sourceId = session.thread.getId();
if (!sourceId) throw new Error('Create or select a thread first');
const t = await session.clone({ sourceThreadId: sourceId });
Defensive patterns

Strategy: type-guard

Validate before calling

if (!sourceThreadId && session.thread.getId() === null) throw new Error('Create or select a thread before cloning');

Type guard

function canClone(s: { thread: { getId(): string | null } }, sourceThreadId?: string): boolean {
  return Boolean(sourceThreadId ?? s.thread.getId());
}

Try / catch

try {
  return await session.clone({ sourceThreadId });
} catch (e) {
  if (e instanceof Error && e.message === 'No source thread to clone') {
    return null; // or create a thread first
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling clone() with no arguments on a session that never bound a thread; calling clone({ sourceThreadId: undefined }) explicitly; calling after unbinding the thread.

Common situations: Forking 'the current conversation' before any conversation exists; wiring a clone button active on a fresh session; a flow that cleared the thread id earlier.

Related errors


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