anomalyco/sst · error · VisibleError
Cannot configure health check for "${k}". Make sure it is de
Error message
Cannot configure health check for "${k}". Make sure it is defined in "loadBalancer.ports". What it means
Health checks in SST's Service load balancer are keyed by "port/protocol" and every key must correspond to a forward target defined in loadBalancer.ports (derived from the rules). A health check entry referencing an unknown "port/protocol" string means it would never attach to a real target group.
Source
Thrown at platform/src/components/aws/service.ts:2082
);
// normalize public/private
const pub = output(inlineLoadBalancer).apply((lb) =>
"public" in lb ? lb.public ?? true : true,
);
// normalize health check
const health = all([type, rules, inlineLoadBalancer]).apply(
([type, rules, lb]) =>
Object.fromEntries(
Object.entries(("health" in lb ? lb.health : {}) ?? {}).map(
([k, v]) => {
if (
!rules.find(
(r) => `${r.forwardPort}/${r.forwardProtocol}` === k,
)
)
throw new VisibleError(
`Cannot configure health check for "${k}". Make sure it is defined in "loadBalancer.ports".`,
);
const protocol = k.split("/")[1];
return [
k,
{
path: ["http", "https"].includes(protocol)
? v.path ?? "/"
: undefined,
interval: v.interval ? toSeconds(v.interval) : 30,
timeout: v.timeout
? toSeconds(v.timeout)
: type === "application"
? 5
: 6,
healthyThreshold: v.healthyThreshold ?? 5,
unhealthyThreshold: v.unhealthyThreshold ?? 2,
protocol: ["http", "https"].includes(protocol)View on GitHub (pinned to a0bd20f762)
Solutions
- Change the health key to exactly match a forward target, e.g. "80/http"
- Add the corresponding port to loadBalancer.ports if the container really exposes it
- Fix typos in port or protocol segment of the key
Example fix
// before
ports: { "80/http": "app:3000" }, health: { "3000/http": "/healthz" }
// after
ports: { "80/http": "app:3000" }, health: { "80/http": "/healthz" } Defensive patterns
Strategy: validation
Validate before calling
const forwardKeys = new Set(config.loadBalancer.rules.map(r => {
const [lp, lproto] = r.listen.split("/");
const [fp, fproto] = r.forward ? r.forward.split("/") : [lp, lproto];
return `${fp}/${fproto}`;
}));
for (const k of Object.keys(config.loadBalancer.health ?? {}))
if (!forwardKeys.has(k)) throw new Error(`health key "${k}" not in ports`); Type guard
null
Try / catch
null
Prevention
- Derive health keys from the same constants used for ports
- Remember health keys use the forward port/protocol, not the listen port
- Keep port and health definitions adjacent in config to spot drift
When it happens
Trigger: Setting loadBalancer.health with a key like "8080/http" when ports only define "80/http", or a typo such as "80/htpp" or "3000" without the protocol suffix.
Common situations: Renaming container ports without updating health check keys; copying health config from another service on different ports; forgetting health keys use forwardPort/forwardProtocol, not the listen port.
Related errors
- Protocols must be either all http/https, or all tcp/udp/tcp_
- The listen protocol "${v.listen}" must match the forward pro
- Protocols must be either all http/https, or all tcp/udp/tcp_
- You must provide at least one rule in "loadBalancer.rules" w
- You must provide a "container" name in each rule when there
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/54eadba896782c29.
Report an issue: GitHub.