anomalyco/sst · error · VisibleError
Invalid rule conditions for listen protocol "${v.listen}". O
Error message
Invalid rule conditions for listen protocol "${v.listen}". Only "http" protocols support conditions. What it means
ALB path/query/header-based routing conditions only exist on application (HTTP/HTTPS) listeners. When a rule listens on a network protocol (tcp/tls/udp) but also specifies `conditions` (path, query, or header), SST's `normalizeLoadBalancer` throws this `VisibleError` because NLB listeners cannot evaluate such conditions.
Source
Thrown at platform/src/components/aws/service.ts:1982
);
});
}
// parse protocols and ports
const rules = lbRules.map((v) => {
const listenParts = v.listen.split("/");
const listenPort = parseInt(listenParts[0]);
const listenProtocol = listenParts[1];
const listenConditions =
v.conditions || v.path
? {
path: v.conditions?.path ?? v.path,
query: v.conditions?.query,
header: v.conditions?.header,
}
: undefined;
if (protocolType(listenProtocol) === "network" && listenConditions)
throw new VisibleError(
`Invalid rule conditions for listen protocol "${v.listen}". Only "http" protocols support conditions.`,
);
const redirectParts = v.redirect?.split("/");
const redirectPort = redirectParts && parseInt(redirectParts[0]);
const redirectProtocol = redirectParts && redirectParts[1];
if (redirectPort && redirectProtocol) {
if (
protocolType(listenProtocol) !== protocolType(redirectProtocol)
)
throw new VisibleError(
`The listen protocol "${v.listen}" must match the redirect protocol "${v.redirect}".`,
);
return {
type: "redirect" as const,
listenPort,
listenProtocol,
listenConditions,View on GitHub (pinned to a0bd20f762)
Solutions
- Remove the `conditions` (and `path`) fields from rules that listen on tcp/tls/udp protocols.
- Change the listen protocol to "http"/"https" if host/path-based routing is actually required.
- Move path-based routing to an application-level router (e.g. API Gateway or an app-level reverse proxy) for network listeners.
Example fix
// before
{ listen: "9000/tcp", conditions: { path: "/api" }, forward: "9000/tcp" }
// after
{ listen: "9000/tcp", forward: "9000/tcp" } Defensive patterns
Strategy: validation
Validate before calling
const isNetworkProto = (p: string) => /^(tcp|tls|udp|tcp_udp)\//.test(p);
for (const r of rules) {
if (isNetworkProto(r.listen) && (r.conditions || r.path)) {
throw new Error(`Rule ${r.listen} cannot use conditions with a network protocol`);
}
} Type guard
function ruleConditionsValid(r: { listen: string; conditions?: object; path?: string }): boolean {
const network = /^(tcp|tls|udp)/.test(r.listen);
return !(network && (r.conditions !== undefined || r.path !== undefined));
} Try / catch
try {
const svc = new sst.aws.Service("Api", args);
} catch (e) {
if (e instanceof VisibleError && e.message.includes("Only \"http\" protocols support conditions")) {
args.loadBalancer.rules = args.loadBalancer.rules.map(({ conditions, path, ...r }) => r);
} else throw e;
} Prevention
- Strip `conditions`/`path` from any rule listening on tcp/tls/udp.
- Only use path/query/header routing on http/https listeners.
- Lint load-balancer rule arrays for protocol/condition compatibility.
When it happens
Trigger: A load balancer rule like `{ listen: "9000/tcp", conditions: { path: "/api" } }` — network listen protocol combined with any `conditions` object (including legacy `path`).
Common situations: Copying an HTTP rule's conditions onto a TCP/UDP rule when adding a non-HTTP port; switching `listen` from "443/https" to "443/tls" and leaving `path`/`conditions` in place.
Related errors
- The listen protocol "${v.listen}" must match the redirect pr
- Cannot access `nodes.loadBalancer` when no public ports are
- You must provide the ports to expose via "loadBalancer.rules
- You must provide a container name in "loadBalancer.rules" wh
- Cannot access `nodes.loadBalancer` in dev mode.
AI-assisted analysis of anomalyco/sst@a0bd20f762 (2026-08-30).
Data as JSON: /api/errors/7b9b2e8b7db75692.
Report an issue: GitHub.