{"record":{"id":"ae5bd71a47fa4bb6","repo":"anomalyco/sst","slug":"protocols-must-be-either-all-http-https-or-all-tc-ae5bd7","errorCode":null,"errorMessage":"Protocols must be either all http/https, or all tcp/udp/tcp_udp/tls.","messagePattern":"Protocols must be either all http/https, or all tcp/udp/tcp_udp/tls\\.","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/service.ts","lineNumber":2029,"sourceCode":"                `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)\n            throw new VisibleError(\n              `Protocols must be either all http/https, or all tcp/udp/tcp_udp/tls.`,\n            );\n\n          // validate certificate exists for https/tls protocol\n          rules.forEach((rule) => {\n            if ([\"https\", \"tls\"].includes(rule.listenProtocol) && !lb.domain) {\n              throw new VisibleError(\n                `You must provide a custom domain for ${rule.listenProtocol.toUpperCase()} protocol.`,\n              );\n            }\n          });\n\n          return rules;\n        },\n      );\n\n      // normalize domain\n      const domain = output(inlineLoadBalancer).apply((lb) => {","sourceCodeStart":2011,"sourceCodeEnd":2047,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/service.ts#L2011-L2047","documentation":"A single ALB listener set must be homogeneous: SST groups rules into application (http/https) or network (tcp/udp/tcp_udp/tls) listeners, and an Elastic Load Balancer cannot mix listener types in one load balancer configuration. normalizeLoadBalancer throws when some but not all rules are application-protocol rules.","triggerScenarios":"Providing loadBalancer.rules where one rule listens on \"80/http\" and another on \"8080/tcp\", or \"443/https\" mixed with \"9000/tls\".","commonSituations":"Adding a gRPC/TLS port next to existing HTTP rules; migrating a service from HTTP to TCP listeners while leaving an old rule behind; merging configs from two services.","solutions":["Make all rules use http/https, or all use tcp/udp/tcp_udp/tls","Move the odd-protocol listener into a separate Service or a separately defined load balancer","Drop the rule that no longer applies"],"exampleFix":"// before\nrules: [{ listen: \"80/http\" }, { listen: \"8080/tcp\" }]\n// after\nrules: [{ listen: \"80/http\" }, { listen: \"8080/http\" }]","handlingStrategy":"validation","validationCode":"const families = new Set(config.loadBalancer.rules.map(r =>\n  [\"http\",\"https\"].includes(r.listen.split(\"/\")[1]) ? \"app\" : \"network\"));\nif (families.size > 1) throw new Error(\"all rules must be http/https or all tcp/udp/tcp_udp/tls\");","typeGuard":"const allSameFamily = (rules: { listen: string }[]) => {\n  const fam = (p: string) => [\"http\",\"https\"].includes(p) ? \"app\" : \"network\";\n  return rules.every(r => fam(r.listen.split(\"/\")[1]) === fam(rules[0].listen.split(\"/\")[1]));\n};","tryCatchPattern":"null","preventionTips":["Standardize each service on one protocol family","Split mixed-protocol workloads into separate Services","Lint loadBalancer configs before deploy"],"tags":["load-balancer","validation","aws","protocol"],"backgroundTag":"protocol-mismatch","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}