mastra-ai/mastra · error

Factory kickoff was queued onto an ending run and never reac

Error message

Factory kickoff was queued onto an ending run and never reached the agent.

What it means

During a kick-off retry against an in-flight run, the dispatcher queued the kickoff message onto the run as it was ending. sendKickoff returns a settled result whose action must be 'wake' to prove the message reached the agent; any other action (or no result) means the kickoff was swallowed by a terminating run and the card would strand. The library throws so the record is retried with a fresh dedupe-safe kickoff key.

Source

Thrown at mastracode/factory/src/rules/dispatcher.ts:987

            );
          try {
            let settled = await sendKickoff(`factory-kickoff:${record.kickoffKey}`);
            if (settled?.action === 'deliver') {
              // `deliver` only proves the signal was queued onto a run already
              // in flight. If that run ends without draining its queue the
              // kickoff is dropped silently. There is no per-notification
              // "processed" signal, so wait for the in-flight run to end and
              // redeliver into the idle session unconditionally — the
              // generation-scoped dedupeKey defeats inbox dedupe and the
              // kickoff key keeps a duplicate run bounded, while a dropped
              // kickoff strands the card forever.
              if (!(await waitForAgentEndOrTimeout(agentEnd, this.#skillCompletionObservationTimeoutMs))) {
                throw new Error('Factory kickoff is waiting on a run that has not ended.');
              }
              armAgentEnd();
              settled = await sendKickoff(`factory-kickoff:${record.kickoffKey}:retry:${record.attempts}`);
              if (settled?.action !== 'wake') {
                throw new Error('Factory kickoff was queued onto an ending run and never reached the agent.');
              }
            }
            const observed = await waitForAgentEndOrTimeout(agentEnd, this.#skillCompletionObservationTimeoutMs);
            if (!observed) {
              throw new Error('Factory kickoff run terminal event was not observed before timeout.');
            } else if (endReason === 'error') {
              throw new Error('Factory kickoff run ended in error.');
            } else if (endReason === 'aborted') {
              // Retryable for the same reason as skill decisions: the dominant
              // cause is the process going away underneath the run, not a
              // deliberate stop, and a spurious retry is bounded by
              // MAX_ATTEMPTS while a dead card costs a human a manual nudge.
              throw new Error('Factory kickoff run was aborted before it finished.');
            }
          } finally {
            unsubscribe();
          }
        },

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Rely on the built-in retry: the throw marks the pending start failed with a retryAt schedule; ensure MAX_ATTEMPTS is not exhausted.
  2. Verify the inbox/dedupe layer is not swallowing retried kickoffs (each retry uses ':retry:<attempts>' in the key — check the key is unique).
  3. Check agent/session logs for the run's end event timing; if teardown routinely races delivery, serialize kickoff after confirmed run end.
  4. Ensure the agent process is stable (no crashes mid-run) — process restarts are the dominant cause per the surrounding code.
Defensive patterns

Strategy: retry

Try / catch

try {
  await dispatcher.dispatch(record);
} catch (e) {
  if (String(e?.message).includes('never reached the agent')) {
    await scheduleRetry(record); // bounded by MAX_ATTEMPTS; kickoff key is attempt-suffixed
  } else throw e;
}

Prevention

When it happens

Trigger: sendKickoff resolved with settled.action !== 'wake' — the run terminated between armAgentEnd() and delivery, the inbox rejected the message via dedupe, or the delivery landed after the agent stopped accepting input.

Common situations: Race between run teardown and message delivery under load; duplicate kickoff messages where generation-scoped dedupeKey suppressed a retry delivery; process crash mid-delivery; attempting wake on a run that already emitted its end event.

Related errors


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