mastra-ai/mastra · error

No active agent run found for signal target

Error message

No active agent run found for signal target

What it means

Thrown by the signal-sending path (sendSignal / signal APIs) when no resourceId/threadId can be resolved from the target or from an active run record, i.e. there is no active agent run matching the signal target. The runtime cannot determine which thread the signal belongs to.

Source

Thrown at packages/core/src/agent/thread-stream-runtime.ts:2811

        } else {
          // Stale cross-pod entry. Clean it up from the local map, then let the lease decide
          state.activeThreadRunIds.delete(key);
          state.activeThreadStreamIds.delete(key);
        }
      }
    }

    if (runId) {
      activeRecord ??= state.threadRunsById.get(runId);
      if (activeRecord) {
        key ??= this.#threadKey(activeRecord.resourceId, activeRecord.threadId);
      }
    }

    const resourceId = target.resourceId ?? activeRecord?.resourceId;
    const threadId = target.threadId ?? activeRecord?.threadId;
    if (!resourceId || !threadId) {
      throw new Error('No active agent run found for signal target');
    }

    const isActiveTarget = Boolean(
      runId && (activeRecord?.output.status === 'running' || (key && state.activeThreadRunIds.get(key) === runId)),
    );
    let signal = createSignal({
      ...signalInput,
      id: signalInput.id ?? this.#generateSignalMessageId(agent, { resourceId, threadId }),
      acceptedAt: new Date(),
    });

    // Resolve conditional delivery attributes now that we know the delivery path.
    signal = resolveDeliveryAttributes(
      signal,
      isActiveTarget ? target.ifActive?.attributes : target.ifIdle?.attributes,
    );

    if (isActiveTarget && activeBehavior !== 'deliver') {

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Pass explicit resourceId and threadId in the target instead of relying on an active run lookup.
  2. Before signaling, confirm the run is still active (e.g. check run status) and handle the finished-run case.
  3. Use ifIdle options so the signal has a defined idle-path target with full thread IDs.

Example fix

// before
await runtime.sendSignal(agent, signalInput, { runId }); // run may be gone
// after
await runtime.sendSignal(agent, signalInput, { runId, resourceId: 'user-1', threadId: 'thread-1' });
Defensive patterns

Strategy: validation

Validate before calling

if (!target.resourceId || !target.threadId) {
  // resolve from your own run registry before signaling
  const rec = myRuns.get(target.runId);
  if (!rec || rec.status !== 'running') throw new Error('No active run for signal target');
  target.resourceId ??= rec.resourceId;
  target.threadId ??= rec.threadId;
}

Type guard

null

Try / catch

try {
  return await runtime.sendSignal(agent, input, target);
} catch (e) {
  if (e instanceof Error && e.message === 'No active agent run found for signal target') {
    // run already finished or unknown runId — treat as a no-op or recreate context
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling the signal API with only a runId whose record is no longer active (run finished/cleaned up), or with an empty target and no running thread run; race where the run completed between lookup and signal dispatch.

Common situations: Signaling a run after it already finished (async listener fires late); stale runIds cached by the client; signaling on a server instance that doesn't own the run (distributed setups without shared pubsub state).

Related errors


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