anomalyco/sst · error · VisibleError

Missing "vpc.containerSubnets" for the

Error message

Missing "vpc.containerSubnets" for the "${name}" Cluster component.

What it means

After deprecating serviceSubnets, Cluster requires subnet IDs under vpc.containerSubnets so it knows which subnets to place tasks/containers in. If neither containerSubnets nor serviceSubnets is provided, SST cannot place the cluster's services and throws.

Solutions

  1. Provide vpc.containerSubnets with an array of private subnet IDs from your VPC.
  2. Alternatively pass a sst.aws.Vpc component instance instead of a raw object.
  3. Ensure the given subnets are routable by your tasks (typically private subnets with NAT).

Example fix

// before
const cluster = new sst.aws.Cluster('MyCluster', { vpc: {} });
// after
const cluster = new sst.aws.Cluster('MyCluster', {
  vpc: { containerSubnets: ['subnet-0abc', 'subnet-1def'] }
});
Defensive patterns

Strategy: validation

Validate before calling

function requireContainerSubnets(vpc) {
  if (!vpc?.containerSubnets && !vpc?.serviceSubnets)
    throw new Error('Cluster vpc.containerSubnets is required (array of subnet IDs)');
}
requireContainerSubnets(vpcConfig);

Type guard

const hasContainerSubnets = (vpc) => Array.isArray(vpc?.containerSubnets) && vpc.containerSubnets.length > 0;

Prevention

When it happens

Trigger: new sst.aws.Cluster('X', { vpc: {} }) or vpc: { cloudmapNamespaceId: ... } with no subnets — normalizeVpc's !containerSubnets && !serviceSubnets branch fires.

Common situations: VPC arg left as an empty object after removing deprecated fields; switching from a Vpc component instance to a raw object but forgetting subnets; partially deleted config.

Related errors


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

Appendix: source

Thrown at platform/src/components/aws/cluster.ts:285

      if (args.vpc instanceof VpcV1) {
        throw new VisibleError(
          `You are using the "Vpc.v1" component. Please migrate to the latest "Vpc" component.`,
        );
      }

      // "vpc" is a Vpc component
      if (args.vpc instanceof Vpc) {
        return args.vpc;
      }

      // "vpc" is object
      return output(args.vpc).apply((vpc) => {
        if (vpc.containerSubnets && vpc.serviceSubnets)
          throw new VisibleError(
            `You cannot provide both "vpc.containerSubnets" and "vpc.serviceSubnets" in the "${name}" Cluster component. The "serviceSubnets" property has been deprecated. Use "containerSubnets" instead.`,
          );
        if (!vpc.containerSubnets && !vpc.serviceSubnets)
          throw new VisibleError(
            `Missing "vpc.containerSubnets" for the "${name}" Cluster component.`,
          );

        if (
          (vpc.cloudmapNamespaceId && !vpc.cloudmapNamespaceName) ||
          (!vpc.cloudmapNamespaceId && vpc.cloudmapNamespaceName)
        )
          throw new VisibleError(
            `You must provide both "vpc.cloudmapNamespaceId" and "vpc.cloudmapNamespaceName" for the "${name}" Cluster component.`,
          );

        return {
          ...vpc,
          containerSubnets: (vpc.containerSubnets ?? vpc.serviceSubnets)!,
          serviceSubnets: undefined,
        };
      });
    }

View on GitHub (pinned to a0bd20f762)