anomalyco/sst · error · VisibleError

Only one of function, queue, or topic is allowed for the "${

Error message

Only one of function, queue, or topic is allowed for the "${n.name}" bucket notification.

What it means

Bucket notifications in SST allow exactly one target per notification: a Lambda function, an SQS queue, or an SNS topic. Specifying more than one of these in a single notification entry is ambiguous, so SST throws this VisibleError during normalization.

Source

Thrown at platform/src/components/aws/bucket-notification.ts:67

    const bucket = output(args.bucket);
    const notifications = normalizeNotifications();
    const { config, functionBuilders } = createNotificationsConfig();
    const notification = createNotification();

    this.functionBuilders = functionBuilders;
    this.notification = notification;

    function normalizeNotifications() {
      return output(args.notifications).apply((notifications) =>
        notifications.map((n) => {
          const count =
            (n.function ? 1 : 0) + (n.queue ? 1 : 0) + (n.topic ? 1 : 0);
          if (count === 0)
            throw new VisibleError(
              `At least one of function, queue, or topic is required for the "${n.name}" bucket notification.`,
            );
          if (count > 1)
            throw new VisibleError(
              `Only one of function, queue, or topic is allowed for the "${n.name}" bucket notification.`,
            );

          return {
            ...n,
            events: n.events ?? [
              "s3:ObjectCreated:*",
              "s3:ObjectRemoved:*",
              "s3:ObjectRestore:*",
              "s3:ReducedRedundancyLostObject",
              "s3:Replication:*",
              "s3:LifecycleExpiration:*",
              "s3:LifecycleTransition",
              "s3:IntelligentTiering",
              "s3:ObjectTagging:*",
              "s3:ObjectAcl:Put",
            ],
          };

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Keep only one target per notification entry and create additional notification entries for other targets
  2. Use an SNS topic as the single target with multiple subscribers to fan out events
  3. Remove the redundant `queue` or `topic` property if one target is leftover from an edit

Example fix

// before
notifications: [{
  name: "onUpload",
  function: "src/handler.handler",
  queue: myQueue.arn,
  events: ["s3:ObjectCreated:*"],
}]
// after
notifications: [{
  name: "onUpload",
  function: "src/handler.handler",
  events: ["s3:ObjectCreated:*"],
}]
Defensive patterns

Strategy: validation

Validate before calling

const fixed = raw.map(n => {
  const targets = [n.function, n.queue, n.topic].filter(Boolean).length;
  if (targets > 1) throw new Error(`Only one target allowed for notification "${n.name}"`);
  return n;
});

Type guard

function hasSingleTarget(n: { function?: unknown; queue?: unknown; topic?: unknown }): boolean {
  return [n.function, n.queue, n.topic].filter(Boolean).length === 1;
}

Try / catch

try {
  new sst.aws.Bucket("B", { notifications: raw });
} catch (e) {
  if ((e as Error).message.includes("Only one of function, queue, or topic is allowed")) {
    console.error("Split the notification into separate entries, one per target");
  }
  throw e;
}

Prevention

When it happens

Trigger: A single `notifications` entry passed to `bucket.notifications` with two or more of `function`, `queue`, and `topic` set simultaneously.

Common situations: Merging two notification configs and keeping both targets; intending to fan out to multiple destinations and mistakenly putting them in one entry instead of creating separate notification entries or using SNS fan-out.

Related errors


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