{"record":{"id":"4542bf1772f9ec38","repo":"anomalyco/sst","slug":"the-listen-protocol-v-listen-must-match-the-f","errorCode":null,"errorMessage":"The listen protocol \"${v.listen}\" must match the forward protocol \"${v.forward}\".","messagePattern":"The listen protocol \"(.+?)\" must match the forward protocol \"(.+?)\"\\.","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/service.ts","lineNumber":2010,"sourceCode":"              )\n                throw new VisibleError(\n                  `The listen protocol \"${v.listen}\" must match the redirect protocol \"${v.redirect}\".`,\n                );\n              return {\n                type: \"redirect\" as const,\n                listenPort,\n                listenProtocol,\n                listenConditions,\n                redirectPort,\n                redirectProtocol,\n              };\n            }\n\n            const forwardParts = v.forward ? v.forward.split(\"/\") : listenParts;\n            const forwardPort = forwardParts && parseInt(forwardParts[0]);\n            const forwardProtocol = forwardParts && forwardParts[1];\n            if (protocolType(listenProtocol) !== protocolType(forwardProtocol))\n              throw new VisibleError(\n                `The listen protocol \"${v.listen}\" must match the forward protocol \"${v.forward}\".`,\n              );\n            return {\n              type: \"forward\" as const,\n              listenPort,\n              listenProtocol,\n              listenConditions,\n              forwardPort,\n              forwardProtocol,\n              container: v.container ?? containers[0].name,\n            };\n          });\n\n          // validate protocols are consistent\n          const appProtocols = rules.filter(\n            (rule) => protocolType(rule.listenProtocol) === \"application\",\n          );\n          if (appProtocols.length > 0 && appProtocols.length < rules.length)","sourceCodeStart":1992,"sourceCodeEnd":2028,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/service.ts#L1992-L2028","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Change the forward protocol to the same family as the listen protocol (e.g. forward \"80/http\" for an https listener)","Remove the forward override entirely so it defaults from the listen value (`forwardParts = listenParts`)","If you truly need cross-protocol forwarding, split into rules that keep families consistent"],"exampleFix":"// before\n{ listen: \"443/https\", forward: \"80/tcp\" }\n// after\n{ listen: \"443/https\", forward: \"80/http\" }","handlingStrategy":"validation","validationCode":"function isApplication(p) { return [\"http\",\"https\"].includes(p?.split(\"/\")[1]); }\nfor (const r of config.loadBalancer.rules) {\n  const lp = r.listen.split(\"/\")[1];\n  const fp = r.forward ? r.forward.split(\"/\")[1] : lp;\n  if ((isApplication(lp)) !== (isApplication(fp))) throw new Error(`rule ${r.listen} -> ${r.forward}: protocols must be same family`);\n}","typeGuard":"const protocolFamily = (p?: string) =>\n  p === undefined ? undefined :\n  [\"http\",\"https\"].includes(p) ? \"application\" :\n  [\"tcp\",\"udp\",\"tcp_udp\",\"tls\"].includes(p) ? \"network\" : \"unknown\";","tryCatchPattern":"null","preventionTips":["Omit forward and let it inherit from listen whenever possible","Keep a comment on each rule noting the protocol family","Validate rule configs in CI with a schema (zod) that constrains protocol pairs"],"tags":["load-balancer","validation","aws","fargate"],"backgroundTag":"protocol-mismatch","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}