mastra-ai/mastra · error · MastraError

AGENT_SEND_STREAM_RESUME_NO_SUSPENDED_THREAD_RUN

AGENT_SEND_STREAM_RESUME_NO_SUSPENDED_THREAD_RUN

Error message

Agent "${this.name}" sendStreamResume() could not find a suspended run "${runId}" for thread "${threadId}".

What it means

Thrown by Agent.sendStreamResume() when the required identifiers were supplied but no suspended run matching the given runId (and optional toolCallId) could be found for the given threadId/resourceId in storage. The resume target does not exist or is no longer in a suspended/resumable state.

Source

Thrown at packages/core/src/agent/agent.ts:9337

      try {
        ({ runs: suspendedRuns } = await this.listSuspendedRuns({ threadId, resourceId }));
      } catch (error) {
        if (!(error instanceof MastraError) || error.id !== 'AGENT_LIST_SUSPENDED_RUNS_NO_STORAGE') {
          throw error;
        }
      }

      const storedRun = suspendedRuns.find(
        run =>
          run.runId === runId && (!toolCallId || run.toolCalls.some(toolCall => toolCall.toolCallId === toolCallId)),
      );
      if (storedRun) {
        resumableRun = { runId, toolCallId };
      }
    }

    if (!resumableRun) {
      throw new MastraError({
        id: 'AGENT_SEND_STREAM_RESUME_NO_SUSPENDED_THREAD_RUN',
        domain: ErrorDomain.AGENT,
        category: ErrorCategory.USER,
        text: `Agent "${this.name}" sendStreamResume() could not find a suspended run "${runId}" for thread "${threadId}".`,
        details: {
          threadId,
          resourceId,
          runId,
          agentName: this.name,
        },
      });
    }

    const resumeOptions = (streamOptions ?? {}) as AgentExecutionOptionsBase<unknown> & { toolCallId?: string };

    await agentThreadStreamRuntime.queueStreamResume(
      runId,
      async () => {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Verify the runId, threadId, and resourceId exactly match the original suspended run
  2. Check storage (the agent's memory/storage adapter) for the run's current status before resuming
  3. Handle already-resumed/completed runs idempotently in your app instead of resuming twice
  4. Reduce storage retention or avoid manual cleanup of suspended runs
  5. Persist runId/threadId/resourceId together when the stream suspends

Example fix

// before
await agent.sendStreamResume({ threadId, resourceId, runId }); // stale runId
// after
const runs = await agent.listSuspendedStreamRuns({ threadId, resourceId });
if (runs.includes(runId)) {
  await agent.sendStreamResume({ threadId, resourceId, runId });
}
Defensive patterns

Strategy: fallback

Validate before calling

const suspended = await agent.listSuspendedStreamRuns({ threadId, resourceId });
if (!suspended.includes(runId)) {
  throw new Error(`run ${runId} is not suspended for thread ${threadId}`);
}

Try / catch

try {
  await agent.sendStreamResume({ threadId, resourceId, runId });
} catch (e) {
  if (e instanceof MastraError && e.id === 'AGENT_SEND_STREAM_RESUME_NO_SUSPENDED_THREAD_RUN') {
    logger.warn('run not resumable; checking current state', { threadId, runId });
    // fall back to inspecting run state or starting a new run
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling sendStreamResume() with a runId that was never suspended, already resumed/completed, purged from storage, or stored under a different threadId/resourceId than passed.

Common situations: Resuming after storage retention/cleanup removed the run, typo'd or stale runId from an old session, resuming a run that already completed, passing resourceId that differs from the one used when the run started.

Related errors


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