{"record":{"id":"23da610b29efb45c","repo":"anomalyco/sst","slug":"you-must-provide-the-ports-to-expose-via-loadbala","errorCode":null,"errorMessage":"You must provide the ports to expose via \"loadBalancer.rules\".","messagePattern":"You must provide the ports to expose via \"loadBalancer\\.rules\"\\.","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/service.ts","lineNumber":1954,"sourceCode":"        return v;\n      });\n    }\n\n    function normalizeLoadBalancer() {\n      const loadBalancer = args.loadBalancer ?? args.public;\n      if (!loadBalancer) return;\n      // ALB attachment case is handled by detectAlbAttachment() before this is called\n      const inlineLoadBalancer = output(loadBalancer).apply(\n        (lb) => lb as Exclude<typeof lb, { instance: Alb }>,\n      );\n\n      // normalize rules\n      const rules = all([inlineLoadBalancer, containers]).apply(\n        ([lb, containers]) => {\n          // validate rules\n          const lbRules = lb.rules ?? lb.ports;\n          if (!lbRules || lbRules.length === 0)\n            throw new VisibleError(\n              `You must provide the ports to expose via \"loadBalancer.rules\".`,\n            );\n\n          // validate container defined when multiple containers exists\n          if (containers.length > 1) {\n            lbRules.forEach((v) => {\n              if (!v.container)\n                throw new VisibleError(\n                  `You must provide a container name in \"loadBalancer.rules\" when there is more than one container.`,\n                );\n            });\n          }\n\n          // parse protocols and ports\n          const rules = lbRules.map((v) => {\n            const listenParts = v.listen.split(\"/\");\n            const listenPort = parseInt(listenParts[0]);\n            const listenProtocol = listenParts[1];","sourceCodeStart":1936,"sourceCodeEnd":1972,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/service.ts#L1936-L1972","documentation":"When a Service uses a managed load balancer, SST needs at least one routing rule to know which container ports to expose. `normalizeLoadBalancer` reads `loadBalancer.rules ?? loadBalancer.ports`; if both are missing or empty it throws this `VisibleError`.","triggerScenarios":"Passing `loadBalancer: {}` (or an object with empty `rules`/`ports` arrays) to `new sst.aws.Service(...)` while not using inline container `public` ports.","commonSituations":"Migrating from an older config where ports were set on containers; refactoring `ports` into `rules` and leaving neither; template code where the ports block was deleted.","solutions":["Add `loadBalancer: { ports: [{ http: 80, https: 443 }] }` (or `rules: [...]`) to the Service.","Alternatively define public ports inline on the container (`containers[].public.ports`) so routing is derived.","If no load balancing is wanted, remove the `loadBalancer` prop entirely instead of passing an empty object."],"exampleFix":"// before\nconst svc = new sst.aws.Service(\"Api\", {\n  cluster,\n  loadBalancer: {}\n});\n\n// after\nconst svc = new sst.aws.Service(\"Api\", {\n  cluster,\n  loadBalancer: { ports: [{ http: 80 }] }\n});","handlingStrategy":"validation","validationCode":"// validate before constructing the Service\nconst lb = args.loadBalancer;\nconst hasRules = lb && ((lb.rules?.length ?? 0) > 0 || (lb.ports?.length ?? 0) > 0);\nif (lb && !hasRules) throw new Error(\"Provide loadBalancer.rules or loadBalancer.ports\");","typeGuard":"function hasLbRules(lb?: { rules?: unknown[]; ports?: unknown[] }): boolean {\n  return !!lb && ((lb.rules?.length ?? 0) > 0 || (lb.ports?.length ?? 0) > 0);\n}","tryCatchPattern":"try {\n  const svc = new sst.aws.Service(\"Api\", args);\n} catch (e) {\n  if (e instanceof VisibleError && e.message.includes(\"loadBalancer.rules\")) {\n    args.loadBalancer = { ports: [{ http: 80 }] }; // retry with defaults\n  } else throw e;\n}","preventionTips":["Never pass an empty `loadBalancer: {}`; always include `ports` or `rules`.","When migrating from inline container ports to LB rules, keep at least one rule.","Remove the `loadBalancer` prop entirely if no public load balancing is needed."],"tags":["aws","ecs","alb","configuration","sst"],"backgroundTag":"missing-required-config","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}