anomalyco/sst · error · VisibleError

At least one condition (path, query, or header) must be set

Error message

At least one condition (path, query, or header) must be set for rules on an external ALB in Service "${name}".

What it means

Unlike an SST-managed ALB where a rule can act as a default catch-all, rules on an external/shared ALB must be distinguishable so they can be translated into AWS listener conditions. Each rule therefore needs at least one of path, query, or header conditions.

Source

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

          );
        }

        const seen =
          prioritiesByListener.get(rule.listen) ?? new Set();
        if (seen.has(rule.priority)) {
          throw new VisibleError(
            `Duplicate priority ${rule.priority} on listener "${rule.listen}" in Service "${name}".`,
          );
        }
        seen.add(rule.priority);
        prioritiesByListener.set(rule.listen, seen);

        if (
          !rule.conditions?.path &&
          !rule.conditions?.query &&
          !rule.conditions?.header
        ) {
          throw new VisibleError(
            `At least one condition (path, query, or header) must be set for rules on an external ALB in Service "${name}".`,
          );
        }

        const listenerParts = rule.listen.split("/");
        const listenerPort = parseInt(listenerParts[0]);
        const listenerProtocol = listenerParts[1];

        const forwardParts = rule.forward.split("/");
        const forwardPort = parseInt(forwardParts[0]);
        const forwardProtocol = forwardParts[1].toUpperCase();
        const containerNameForKey = rule.container ?? name;
        const tgtId = targetKey(containerNameForKey, forwardProtocol, forwardPort);

        const targetGroup = albTargets[tgtId];
        if (!targetGroup) {
          throw new VisibleError(
            `Target group "${tgtId}" not found. Ensure the forward port matches in Service "${name}".`,

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Add conditions: { path: "/*" } (or a specific path pattern) to the rule
  2. Add a query or header condition if path-based routing doesn't fit
  3. If a catch-all is genuinely needed, own the default listener rule outside per-service rules

Example fix

// before
rules: [{ listen: "443/https", container: "app" }]
// after
rules: [{ listen: "443/https", container: "app", conditions: { path: "/*" } }]
Defensive patterns

Strategy: validation

Validate before calling

for (const r of attachment.rules) {
  const c = r.conditions ?? {};
  if (!c.path && !c.query && !c.header)
    throw new Error(`rule on ${r.listen} needs a path, query, or header condition`);
}

Type guard

const hasCondition = (r: { conditions?: { path?: string; query?: Record<string, string>; header?: Record<string, string> } }) =>
  Boolean(r.conditions?.path || r.conditions?.query || r.conditions?.header);

Try / catch

null

Prevention

When it happens

Trigger: An ALB attachment rule specifying only listen (and maybe container/forward) with conditions omitted or conditions set to an empty object/undefined fields.

Common situations: Porting rules from a self-managed Service (where catch-all is fine) to a shared ALB; assuming a default rule is created on external listeners; typing conditions but leaving all three sub-fields empty.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


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