anomalyco/sst · error · VisibleError

Cannot subscribe to the "${this.constructorName}" queue mult

Error message

Cannot subscribe to the "${this.constructorName}" queue multiple times. A Cloudflare Queue can only have one consumer.

What it means

SST throws this when `subscribe()` is called more than once on a `sst.cloudflare.Queue`. Cloudflare Queues support at most one consumer per queue, so a second subscription would produce an invalid resource. SST tracks subscription state with `isSubscribed` and fails fast at synth time with a VisibleError.

Source

Thrown at platform/src/components/cloudflare/queue.ts:249

   *
   * Configure batch settings.
   *
   * ```ts title="sst.config.ts"
   * queue.subscribe("consumer.ts", {
   *   batch: {
   *     size: 10,
   *     window: "20 seconds",
   *   },
   * });
   * ```
   */
  public subscribe(
    subscriber: Input<string | WorkerArgs>,
    args?: QueueSubscribeArgs,
    opts?: ComponentResourceOptions,
  ) {
    if (this.isSubscribed) {
      throw new VisibleError(
        `Cannot subscribe to the "${this.constructorName}" queue multiple times. A Cloudflare Queue can only have one consumer.`,
      );
    }

    this.isSubscribed = true;

    const parent = this;
    const name = this.constructorName;

    return new QueueWorkerSubscriber(
      `${name}Subscriber`,
      {
        queue: { id: this.queue.id },
        subscriber,
        accountId: this.constructorArgs?.accountId,
        dlq: this.constructorArgs?.dlq,
        maxConcurrency: this.constructorArgs?.maxConcurrency,
        batch: args?.batch,

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Keep a single `subscribe()` call; move the extra consuming logic into the same subscribed worker
  2. Create a separate Cloudflare Queue for the second consumer and produce to both queues
  3. Use Cloudflare's dead-letter or fan-out patterns (e.g. a worker that re-publishes) instead of multiple direct consumers

Example fix

// before
queue.subscribe(workerA);
queue.subscribe(workerB); // throws
// after
queue.subscribe(workerA);
const queueB = new sst.cloudflare.Queue('QueueB');
workerA.addHandler('fanout', async () => { /* send to queueB */ });
queueB.subscribe(workerB);
Defensive patterns

Strategy: validation

Validate before calling

if (subscribedQueues.has(queue.node.id)) throw new Error(`Queue ${queue.node.id} already subscribed`);
subscribedQueues.add(queue.node.id);
queue.subscribe(worker);

Try / catch

// VisibleError throws at synth time, not runtime
try { queue.subscribe(workerA); } catch (e) { console.error('Queue already has a consumer:', e.message); }

Prevention

When it happens

Trigger: Calling `queue.subscribe(...)` a second time on the same Queue component, e.g. wiring two workers to consume the same queue, or a shared component module that subscribes on import being used twice.

Common situations: Teams adding a second consumer worker to an existing queue; re-exported component wrappers whose module side effects run subscribe again; copy-pasted infra code reusing a queue variable in two stacks/components.

Related errors


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/4b20612c2785b3e6. Report an issue: GitHub.