{"record":{"id":"85cceb4f18c32fdf","repo":"kubernetes/kops","slug":"could-not-determine-cluster-region-no-subnet-spec","errorCode":null,"errorMessage":"could not determine cluster region: no subnet specifies a zone","messagePattern":"could not determine cluster region: no subnet specifies a zone","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awsup/aws_utils.go","lineNumber":117,"sourceCode":"\t\t\t\treturn \"\", fmt.Errorf(\"subnet %q must specify a zone or the ID of an existing subnet\", subnet.Name)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(subnet.Zone) <= 2 {\n\t\t\treturn \"\", fmt.Errorf(\"invalid AWS zone: %q in subnet %q\", subnet.Zone, subnet.Name)\n\t\t}\n\n\t\tzoneRegion := subnet.Zone[:len(subnet.Zone)-1]\n\t\tif region != \"\" && zoneRegion != region {\n\t\t\treturn \"\", fmt.Errorf(\"error Clusters cannot span multiple regions (found zone %q, but region is %q)\", subnet.Zone, region)\n\t\t}\n\n\t\tregion = zoneRegion\n\t}\n\n\tif region == \"\" {\n\t\treturn \"\", fmt.Errorf(\"could not determine cluster region: no subnet specifies a zone\")\n\t}\n\n\treturn region, nil\n}\n\n// SupportsS3BootstrapEndpoint reports whether the region uses the amazonaws.com partition DNS\n// suffix hard-coded by the nodeup bootstrap script. EC2 uses the same partition suffix as S3 and\n// can be resolved without a bucket.\nfunc SupportsS3BootstrapEndpoint(ctx context.Context, region string) (bool, error) {\n\tresolver := ec2.NewDefaultEndpointResolverV2()\n\tendpoint, err := resolver.ResolveEndpoint(ctx, ec2.EndpointParameters{Region: aws.String(region)})\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"resolving EC2 endpoint for region %q: %w\", region, err)\n\t}\n\n\treturn endpoint.URI.Hostname() == fmt.Sprintf(\"ec2.%s.amazonaws.com\", region), nil\n}\n","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awsup/aws_utils.go#L99-L135","documentation":"If none of the cluster's subnets specify a zone (all use subnet IDs instead, or are empty), FindRegion cannot infer a region from the spec alone and returns this error. The library requires at least one zone-based subnet to determine the region without additional cloud lookups. It prevents proceeding with an unknown region that would break S3 state-store and EC2 endpoint selection.","triggerScenarios":"FindRegion finishing the subnet loop with region == \"\" — every subnet had an ID (zone deferred to cloud lookup) or the subnet list effectively carried no zones.","commonSituations":"Clusters defined entirely with existing subnet IDs; minimal test manifests with no zones; tooling that strips zone fields when importing a VPC.","solutions":["Add at least one subnet with an explicit zone (e.g. zone: us-east-1a) to the cluster spec","Or set the region explicitly where supported / provide subnet IDs whose lookup path is used instead of FindRegion","Verify the subnets section is non-empty and populated after `kops edit cluster`"],"exampleFix":"// before\nsubnets:\n- name: existing\n  id: subnet-0abc123\n// after\nsubnets:\n- name: existing\n  id: subnet-0abc123\n  zone: us-east-1a","handlingStrategy":"validation","validationCode":"hasZone := false\nfor _, s := range cluster.Spec.Networking.Subnets {\n    if s.Zone != \"\" { hasZone = true }\n}\nif !hasZone { return fmt.Errorf(\"at least one subnet must specify a zone\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Include at least one zone-based subnet per cluster spec","If using only existing subnet IDs, keep the zone fields populated anyway after lookup","Validate the manifest before create/update"],"tags":["aws","region","subnet","cluster-spec"],"backgroundTag":"missing-subnet-zone","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}