anomalyco/sst · error · VisibleError

Target group "${tgtId}" not found. Ensure the forward port m

Error message

Target group "${tgtId}" not found. Ensure the forward port matches in Service "${name}".

What it means

When a Service is attached to an existing ALB via loadBalancer rules, each rule's `forward` port/protocol must match a target group that the Service created for one of its exposed ports. The component builds a key from the rule's forward port/protocol/container and looks it up in the map of ALB target groups; if nothing matches, it throws this VisibleError so the misconfiguration is caught at synth/deploy time instead of producing an invalid listener rule.

Source

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

        ) {
          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}".`,
          );
        }

        const listenerResource =
          attachment.instance.getListener(listenerProtocol, listenerPort);

        new lb.ListenerRule(
          ...transform(
            args.transform?.listenerRule,
            `${name}AlbRule${listenerProtocol.toUpperCase()}${listenerPort}P${rule.priority}`,
            {
              listenerArn: listenerResource.arn,
              priority: rule.priority,
              actions: [
                {
                  type: "forward",
                  targetGroupArn: targetGroup.arn,

View on GitHub (pinned to a0bd20f762)

Solutions

  1. Check the rule's `forward` port in the Service's loadBalancer attachment and make it exactly match a port exposed by the target container (e.g. change `forward: "8080/http"` to `forward: "3000/http"`).
  2. Verify the protocol in `forward` matches the protocol the Service exposes for that port (http vs https).
  3. If the rule forwards to a non-default container, set `container` on the rule to the container that actually exposes the port.
  4. Confirm the target container declares that port in its `ports`/public ports configuration so the Service creates the target group.

Example fix

// before
loadBalancer: {
  rules: [{ listen: "443/https", forward: "8080/http", conditions: { path: "/api/*" } }]
}
// after
loadBalancer: {
  rules: [{ listen: "443/https", forward: "3000/http", conditions: { path: "/api/*" } }]
}
Defensive patterns

Strategy: validation

Validate before calling

const svcPorts = container.ports?.map(p => `${p.port}/${p.protocol ?? "http"}`) ?? [];
if (!svcPorts.includes(rule.forward)) {
  throw new Error(`Rule forward "${rule.forward}" must match an exposed Service port (${svcPorts.join(", ")})`);
}

Type guard

function hasMatchingTargetGroup(albTargets: Record<string, unknown>, rule: { forward: string; container?: string }, svcName: string): boolean {
  const [port, proto] = rule.forward.split("/");
  const key = targetKey(rule.container ?? svcName, (proto ?? "http").toUpperCase(), parseInt(port, 10));
  return key in albTargets;
}

Try / catch

try {
  await deploy();
} catch (e) {
  if (e instanceof VisibleError && e.message.includes("Target group") && e.message.includes("not found")) {
    console.error("ALB rule forward port does not match an exposed service port:", e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: Setting a loadBalancer rule whose `forward` port (or protocol, or container name) does not correspond to any port exposed by the Service's containers — e.g. `forward: "8080/http"` while the container only exposes/exactly registers port 3000, a protocol mismatch like `forward: "3000/https"` when the target group was created as http, or a `container` field that names a container that has no such port.

Common situations: Copy-pasting an ALB rule from another service and forgetting to update the forward port; renaming a container so the default container-name key no longer matches; typo in port; assuming any forward port works without declaring the port in the container's ports list.

Related errors


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