mastra-ai/mastra · error

OrchestrationWorker requires a pull-capable PubSub, but the

Error message

OrchestrationWorker requires a pull-capable PubSub, but the configured pubsub only supports: ${modes.join(', ')}. Either remove OrchestrationWorker from the workers list or use a pull-capable PubSub (e.g. Redis Streams).

What it means

OrchestrationWorker uses a pull subscription on the workflow topic (PullTransport). init() inspects pubsub.supportedModes (defaulting to ['pull']) and throws when 'pull' is not supported, because push-only transports (EventEmitter, GCP push) would never deliver events to this worker's polling loop.

Source

Thrown at packages/core/src/worker/workers/orchestration-worker.ts:52

  constructor(config: OrchestrationWorkerConfig = {}) {
    super();
    this.#config = config;
  }

  async init(deps: WorkerDeps): Promise<void> {
    await super.init(deps);

    if (!deps.mastra) {
      throw new Error('OrchestrationWorker requires Mastra instance');
    }

    // OrchestrationWorker drives a pull subscription on the workflow topic.
    // Push-only pubsubs (EventEmitter, GCP push subscriptions) deliver events
    // through different paths and must not be paired with this worker.
    const modes = deps.pubsub.supportedModes ?? ['pull'];
    if (!modes.includes('pull')) {
      throw new Error(
        `OrchestrationWorker requires a pull-capable PubSub, but the configured pubsub only supports: ${modes.join(', ')}. ` +
          `Either remove OrchestrationWorker from the workers list or use a pull-capable PubSub (e.g. Redis Streams).`,
      );
    }

    // If MASTRA_STEP_EXECUTION_URL is set, use HttpRemoteStrategy
    // (standalone worker calling back to the server for step execution).
    // The strategy reads MASTRA_WORKER_AUTH_TOKEN itself and forwards it
    // through the server's normal Mastra auth provider — there is no
    // separate "worker secret" gate.
    const remoteUrl = process.env.MASTRA_STEP_EXECUTION_URL;
    if (remoteUrl) {
      this.#strategy = new HttpRemoteStrategy({
        serverUrl: remoteUrl,
      });
    }

    this.#processor = new WorkflowEventProcessor({

View on GitHub (pinned to 75dd419e61)

Solutions

  1. Swap to a pull-capable PubSub such as Redis Streams (or another supportedModes including 'pull')
  2. Remove OrchestrationWorker from the workers list if your infra is push-only and handle workflows in-process instead
  3. Explicitly verify pubsub.supportedModes in your config wiring before startup
  4. For local dev, use a local Redis so the Redis Streams pubsub can run in pull mode

Example fix

// before
new OrchestrationWorker({ name: 'orchestrator', pubsub: new EventEmitterPubSub() })
// after
new OrchestrationWorker({ name: 'orchestrator', pubsub: new RedisStreamsPubSub({ url: process.env.REDIS_URL }) })
Defensive patterns

Strategy: validation

Validate before calling

const modes = pubsub.supportedModes ?? ['pull'];
if (!modes.includes('pull')) throw new Error('OrchestrationWorker needs a pull-capable pubsub');

Type guard

function isPullCapable(p) { return (p.supportedModes ?? ['pull']).includes('pull'); }

Try / catch

try {
  await worker.init(deps);
} catch (e) {
  if (e.message.includes('pull-capable PubSub')) {
    logger.error('Replace pubsub with Redis Streams or remove OrchestrationWorker');
  } else throw e;
}

Prevention

When it happens

Trigger: Configuring OrchestrationWorker with a push-only PubSub implementation whose supportedModes excludes 'pull' — e.g. an EventEmitter-based pubsub or a GCP push subscription — and calling init().

Common situations: Dev setups using the in-memory/EventEmitter pubsub while deploying an OrchestrationWorker; GCP PubSub push subscriptions; copying pubsub config from a push-based worker to the orchestration worker.

Related errors


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