anomalyco/sst · error · VisibleError

The listen protocol "${v.listen}" must match the forward pro

Error message

The listen protocol "${v.listen}" must match the forward protocol "${v.forward}".

What it means

SST's Service load balancer requires that when you override the forward protocol for a rule, it must belong to the same protocol family (application http/https vs network tcp/udp/tcp_udp/tls) as the listen protocol. An ALB/Fargate listener cannot forward to a target group of an incompatible protocol type, so normalizeLoadBalancer rejects the mix at synth time.

Source

Thrown at platform/src/components/aws/service.ts:2010

              )
                throw new VisibleError(
                  `The listen protocol "${v.listen}" must match the redirect protocol "${v.redirect}".`,
                );
              return {
                type: "redirect" as const,
                listenPort,
                listenProtocol,
                listenConditions,
                redirectPort,
                redirectProtocol,
              };
            }

            const forwardParts = v.forward ? v.forward.split("/") : listenParts;
            const forwardPort = forwardParts && parseInt(forwardParts[0]);
            const forwardProtocol = forwardParts && forwardParts[1];
            if (protocolType(listenProtocol) !== protocolType(forwardProtocol))
              throw new VisibleError(
                `The listen protocol "${v.listen}" must match the forward protocol "${v.forward}".`,
              );
            return {
              type: "forward" as const,
              listenPort,
              listenProtocol,
              listenConditions,
              forwardPort,
              forwardProtocol,
              container: v.container ?? containers[0].name,
            };
          });

          // validate protocols are consistent
          const appProtocols = rules.filter(
            (rule) => protocolType(rule.listenProtocol) === "application",
          );
          if (appProtocols.length > 0 && appProtocols.length < rules.length)

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Change the forward protocol to the same family as the listen protocol (e.g. forward "80/http" for an https listener)
  2. Remove the forward override entirely so it defaults from the listen value (`forwardParts = listenParts`)
  3. If you truly need cross-protocol forwarding, split into rules that keep families consistent

Example fix

// before
{ listen: "443/https", forward: "80/tcp" }
// after
{ listen: "443/https", forward: "80/http" }
Defensive patterns

Strategy: validation

Validate before calling

function isApplication(p) { return ["http","https"].includes(p?.split("/")[1]); }
for (const r of config.loadBalancer.rules) {
  const lp = r.listen.split("/")[1];
  const fp = r.forward ? r.forward.split("/")[1] : lp;
  if ((isApplication(lp)) !== (isApplication(fp))) throw new Error(`rule ${r.listen} -> ${r.forward}: protocols must be same family`);
}

Type guard

const protocolFamily = (p?: string) =>
  p === undefined ? undefined :
  ["http","https"].includes(p) ? "application" :
  ["tcp","udp","tcp_udp","tls"].includes(p) ? "network" : "unknown";

Try / catch

null

Prevention

When it happens

Trigger: Defining a loadBalancer.rules entry like listen: "443/https" with forward: "80/tcp", or listen "8080/tls" with forward "80/http" — the protocolType() comparison fails before any AWS resources are created.

Common situations: Copy-pasting listener configs from classic ELB examples; assuming the forward side defaults independently of the listen side; mixing an HTTPS public listener with a TCP container port.

Related errors


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