{"record":{"id":"9a235b89f5b7851d","repo":"anomalyco/sst","slug":"you-must-provide-at-least-one-rule-in-loadbalance","errorCode":null,"errorMessage":"You must provide at least one rule in \"loadBalancer.rules\" when using an external ALB in Service \"${name}\".","messagePattern":"You must provide at least one rule in \"loadBalancer\\.rules\" when using an external ALB in Service \"(.+?)\"\\.","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/service.ts","lineNumber":2617,"sourceCode":"      if (\n        !loadBalancer ||\n        typeof loadBalancer !== \"object\" ||\n        !(\"instance\" in loadBalancer) ||\n        !(loadBalancer.instance instanceof Alb)\n      ) {\n        return undefined;\n      }\n      return loadBalancer;\n    }\n\n    function createAlbTargetsAndEntries(\n      attachment: NonNullable<typeof albAttachment>,\n    ) {\n      const rules = attachment.rules;\n      const health = attachment.health ?? {};\n\n      if (rules.length === 0) {\n        throw new VisibleError(\n          `You must provide at least one rule in \"loadBalancer.rules\" when using an external ALB in Service \"${name}\".`,\n        );\n      }\n\n      // Validate container names (no resources created here)\n      containers.apply((ctrs) => {\n        const containerNames = new Set(ctrs.map((c) => c.name));\n        if (ctrs.length > 1) {\n          for (const rule of rules) {\n            if (!rule.container) {\n              throw new VisibleError(\n                `You must provide a \"container\" name in each rule when there is more than one container in Service \"${name}\".`,\n              );\n            }\n          }\n        }\n        for (const rule of rules) {\n          const cn = rule.container ?? ctrs[0].name;","sourceCodeStart":2599,"sourceCodeEnd":2635,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/service.ts#L2599-L2635","documentation":"When a Service attaches to an external/shared ALB, SST does not create a default catch-all listener rule for you — each rule must be explicit. An attachment with an empty rules array is invalid, so the constructor throws at synth time.","triggerScenarios":"Creating a Service with loadBalancer pointing at an existing ALB (albAttachment) but leaving rules: [] or omitting rules entirely.","commonSituations":"Scaffolding a service and planning to add rules later; assuming internal ALB defaults apply to external ALBs too; converting a self-managed-LB service to a shared ALB without porting the rules.","solutions":["Add at least one rule with listen, container, and conditions (path/query/header)","If the service shouldn't be behind the ALB yet, remove the ALB attachment","Comment out the attachment until rules are ready"],"exampleFix":"// before\nloadBalancer: { external: alb, rules: [] }\n// after\nloadBalancer: { external: alb, rules: [{ listen: \"443/https\", container: \"app\", conditions: { path: \"/*\" } }] }","handlingStrategy":"validation","validationCode":"if (attachment.external && (!attachment.rules || attachment.rules.length === 0))\n  throw new Error(\"external ALB attachment requires at least one rule\");","typeGuard":"const hasRules = (a: { rules?: unknown[] }) => Array.isArray(a.rules) && a.rules.length > 0;","tryCatchPattern":"try {\n  new sst.aws.Service(name, { loadBalancer: { external: alb, rules } });\n} catch (e) {\n  if (String(e).includes('at least one rule')) throw new Error(`Service ${name}: define loadBalancer.rules when using an external ALB`);\n  throw e;\n}","preventionTips":["Never scaffold external-ALB services with empty rules","Convert self-managed LB rules explicitly when moving to a shared ALB","Reject empty rules arrays in your config schema"],"tags":["load-balancer","validation","alb","shared-infrastructure"],"backgroundTag":"missing-required-config","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}