{"record":{"id":"56283a0c5f850de2","repo":"anomalyco/sst","slug":"only-one-of-function-queue-or-topic-is-allowed-f","errorCode":null,"errorMessage":"Only one of function, queue, or topic is allowed for the \"${n.name}\" bucket notification.","messagePattern":"Only one of function, queue, or topic is allowed for the \"(.+?)\" bucket notification\\.","errorType":"exception","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/bucket-notification.ts","lineNumber":67,"sourceCode":"    const bucket = output(args.bucket);\n    const notifications = normalizeNotifications();\n    const { config, functionBuilders } = createNotificationsConfig();\n    const notification = createNotification();\n\n    this.functionBuilders = functionBuilders;\n    this.notification = notification;\n\n    function normalizeNotifications() {\n      return output(args.notifications).apply((notifications) =>\n        notifications.map((n) => {\n          const count =\n            (n.function ? 1 : 0) + (n.queue ? 1 : 0) + (n.topic ? 1 : 0);\n          if (count === 0)\n            throw new VisibleError(\n              `At least one of function, queue, or topic is required for the \"${n.name}\" bucket notification.`,\n            );\n          if (count > 1)\n            throw new VisibleError(\n              `Only one of function, queue, or topic is allowed for the \"${n.name}\" bucket notification.`,\n            );\n\n          return {\n            ...n,\n            events: n.events ?? [\n              \"s3:ObjectCreated:*\",\n              \"s3:ObjectRemoved:*\",\n              \"s3:ObjectRestore:*\",\n              \"s3:ReducedRedundancyLostObject\",\n              \"s3:Replication:*\",\n              \"s3:LifecycleExpiration:*\",\n              \"s3:LifecycleTransition\",\n              \"s3:IntelligentTiering\",\n              \"s3:ObjectTagging:*\",\n              \"s3:ObjectAcl:Put\",\n            ],\n          };","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/bucket-notification.ts#L49-L85","documentation":"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.","triggerScenarios":"A single `notifications` entry passed to `bucket.notifications` with two or more of `function`, `queue`, and `topic` set simultaneously.","commonSituations":"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.","solutions":["Keep only one target per notification entry and create additional notification entries for other targets","Use an SNS topic as the single target with multiple subscribers to fan out events","Remove the redundant `queue` or `topic` property if one target is leftover from an edit"],"exampleFix":"// before\nnotifications: [{\n  name: \"onUpload\",\n  function: \"src/handler.handler\",\n  queue: myQueue.arn,\n  events: [\"s3:ObjectCreated:*\"],\n}]\n// after\nnotifications: [{\n  name: \"onUpload\",\n  function: \"src/handler.handler\",\n  events: [\"s3:ObjectCreated:*\"],\n}]","handlingStrategy":"validation","validationCode":"const fixed = raw.map(n => {\n  const targets = [n.function, n.queue, n.topic].filter(Boolean).length;\n  if (targets > 1) throw new Error(`Only one target allowed for notification \"${n.name}\"`);\n  return n;\n});","typeGuard":"function hasSingleTarget(n: { function?: unknown; queue?: unknown; topic?: unknown }): boolean {\n  return [n.function, n.queue, n.topic].filter(Boolean).length === 1;\n}","tryCatchPattern":"try {\n  new sst.aws.Bucket(\"B\", { notifications: raw });\n} catch (e) {\n  if ((e as Error).message.includes(\"Only one of function, queue, or topic is allowed\")) {\n    console.error(\"Split the notification into separate entries, one per target\");\n  }\n  throw e;\n}","preventionTips":["One target per notification entry; create separate entries for extra targets","Use SNS topic fan-out when multiple consumers need the same events","Centralize notification construction in a helper enforcing the single-target rule"],"tags":["aws","s3","bucket-notification","config-conflict"],"backgroundTag":"ambiguous-configuration","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}