{"record":{"id":"9a974b65c6482271","repo":"anomalyco/sst","slug":"at-least-one-of-function-queue-or-topic-is-requi","errorCode":null,"errorMessage":"At least one of function, queue, or topic is required for the \"${n.name}\" bucket notification.","messagePattern":"At least one of function, queue, or topic is required for the \"(.+?)\" bucket notification\\.","errorType":"exception","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/bucket-notification.ts","lineNumber":63,"sourceCode":"  constructor(name: string, args: Args, opts?: ComponentResourceOptions) {\n    super(__pulumiType, name, args, opts);\n\n    const self = this;\n    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\",","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/bucket-notification.ts#L45-L81","documentation":"Each entry in a bucket's `notifications` array must designate exactly one subscription target. When a notification has none of `function`, `queue`, or `topic` set, SST cannot know where to send the event and throws this VisibleError during normalization.","triggerScenarios":"Passing a `notifications: [{ name: \"x\", events: [...] }]` entry to `bucket.notifications` (or constructor args) with no `function`, `queue`, or `topic` property.","commonSituations":"Copy-pasted notification config with target removed; conditionally built target object that ends up undefined; refactoring from one target type to another and deleting the old key first.","solutions":["Add a `function`, `queue`, or `topic` property to the notification entry","If the target is optional in your config, filter out empty notification entries before passing them to SST","Check that the target resource reference isn't undefined due to a typo"],"exampleFix":"// before\nnotifications: [{ name: \"onUpload\", events: [\"s3:ObjectCreated:*\"] }]\n// after\nnotifications: [{\n  name: \"onUpload\",\n  events: [\"s3:ObjectCreated:*\"],\n  function: \"src/notification.handler\",\n}]","handlingStrategy":"validation","validationCode":"const notifications = rawNotifications.filter(n => n.function || n.queue || n.topic);\nnew sst.aws.Bucket(\"Bucket\", { notifications });","typeGuard":"function hasNotificationTarget(n: { function?: unknown; queue?: unknown; topic?: unknown }): boolean {\n  return Boolean(n.function || n.queue || n.topic);\n}","tryCatchPattern":"try {\n  new sst.aws.Bucket(\"B\", { notifications: raw });\n} catch (e) {\n  if ((e as Error).message.includes(\"At least one of function, queue, or topic is required\")) {\n    console.error(\"Notification entry is missing its target\");\n  }\n  throw e;\n}","preventionTips":["Filter out notification entries with no target before passing to the component","Use a typed interface marking exactly one of function/queue/topic as required","Build targets conditionally but validate the result before deploy"],"tags":["aws","s3","bucket-notification","missing-config"],"backgroundTag":"missing-required-config","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}