anomalyco/sst · error · VisibleError
Cannot access `nodes.loadBalancer` when no public ports are
Error message
Cannot access `nodes.loadBalancer` when no public ports are exposed.
What it means
The Service only creates an Elastic Load Balancer when public ports are exposed (e.g. via the `loadBalancer` args). When none are configured, `self.loadBalancer` is undefined and the getter throws this VisibleError rather than returning `undefined`, since the component cannot silently hand back a missing node.
Source
Thrown at platform/src/components/aws/service.ts:2912
* The Amazon ECS Task Definition.
*/
get taskDefinition() {
if (self.dev)
throw new VisibleError(
"Cannot access `nodes.taskDefinition` in dev mode.",
);
return self.taskDefinition!;
},
/**
* The Amazon Elastic Load Balancer.
*/
get loadBalancer() {
if (self.dev)
throw new VisibleError(
"Cannot access `nodes.loadBalancer` in dev mode.",
);
if (!self.loadBalancer)
throw new VisibleError(
"Cannot access `nodes.loadBalancer` when no public ports are exposed.",
);
return self.loadBalancer;
},
/**
* The Amazon Application Auto Scaling target.
*/
get autoScalingTarget() {
if (self.dev)
throw new VisibleError(
"Cannot access `nodes.autoScalingTarget` in dev mode.",
);
return self.autoScalingTarget!;
},
/**
* The Amazon Cloud Map service.
*/
get cloudmapService() {View on GitHub (pinned to a0bd20f762)
Solutions
- Expose public ports by providing the `loadBalancer` (or `ports`) argument when creating the Service so the ALB is actually created.
- If the service is intentionally private, remove the `nodes.loadBalancer` reference and wire any listener/DNS through another component.
- Conditionally access the node only when your config actually sets a load balancer.
Example fix
// before
const lb = service.nodes.loadBalancer;
// after (option A: expose ports)
const service = new sst.aws.Service("Api", {
cluster,
loadBalancer: { ports: [{ listen: "80/http" }] },
});
const lb = service.nodes.loadBalancer;
// or (option B: guard)
const lb = withLoadBalancer ? service.nodes.loadBalancer : undefined; Defensive patterns
Strategy: validation
Validate before calling
// Ensure the Service was created with a load balancer before reading the node
const service = new sst.aws.Service("Api", {
cluster,
loadBalancer: { ports: [{ listen: "80/http" }] },
});
// only then:
const lb = service.nodes.loadBalancer; Try / catch
try {
const lb = service.nodes.loadBalancer;
} catch (e) {
if (String(e).includes("no public ports")) {
// service is private; use alternative routing or skip
} else throw e;
} Prevention
- Check the Service's `loadBalancer`/ports args before referencing its load balancer node.
- Track whether a service is intentionally private (workers, internal APIs) and never touch ALB nodes for those.
- Centralize load-balancer wiring in one helper that validates config first.
When it happens
Trigger: Reading `service.nodes.loadBalancer` on a Service created without a `loadBalancer`/public `ports` configuration, in deploy mode (not dev).
Common situations: A developer assumes every Service gets an ALB and references `nodes.loadBalancer` for a listener rule or Route53 alias, but the service was declared as internal / non-HTTP (e.g. queue worker or private gRPC service).
Related errors
- You must provide the ports to expose via "public.ports".
- Cannot access `nodes.loadBalancer` when no public ports are
- You must provide the ports to expose via "loadBalancer.rules
- You must provide a container name in "loadBalancer.rules" wh
- Target group "${tgtId}" not found. Ensure the forward port m
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/d674747f919728bf.
Report an issue: GitHub.