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

  1. Change the health key to exactly match a forward target, e.g. "80/http"
  2. Add the corresponding port to loadBalancer.ports if the container really exposes it
  3. 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

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


AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30). Data as JSON: /api/errors/54eadba896782c29. Report an issue: GitHub.