{"record":{"id":"0e67e1bd6490f363","repo":"kubernetes/kops","slug":"invalid-aws-zone-q-in-subnet-q","errorCode":null,"errorMessage":"invalid AWS zone: %q in subnet %q","messagePattern":"invalid AWS zone: %q in subnet %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awsup/aws_utils.go","lineNumber":105,"sourceCode":"\n\treturn fmt.Errorf(\"Region is not a recognized EC2 region: %q (check you have specified valid zones?)\", region)\n}\n\n// FindRegion determines the region from the zones specified in the cluster\nfunc FindRegion(cluster *kops.Cluster) (string, error) {\n\tregion := \"\"\n\n\tfor _, subnet := range cluster.Spec.Networking.Subnets {\n\t\tif subnet.Zone == \"\" {\n\t\t\t// The zone of a subnet specified by ID is looked up from the cloud later.\n\t\t\tif subnet.ID == \"\" {\n\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","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awsup/aws_utils.go#L87-L123","documentation":"AWS availability zone names are region prefix plus a letter (e.g. us-east-1a); FindRegion uses this to derive the region by stripping the final character. If a subnet's zone is 2 characters or fewer it cannot contain a region prefix, so the library rejects it as an invalid AWS zone. This catches misformatted zone values before they produce a bogus region.","triggerScenarios":"FindRegion encountering a subnet whose Zone field length is <= 2 (e.g. \"a\", \"1a\", \"eu\"), triggering the len(subnet.Zone) <= 2 check.","commonSituations":"Users writing just the zone suffix ('a' or 'b') instead of the full zone name; YAML quoting mishaps truncating values; copying GCE zone style ('us-east1-a' is fine but 'a' alone is not).","solutions":["Use the full AWS availability zone name in each subnet's zone field (e.g. us-east-1a, not a)","Fix YAML so the zone value is not truncated or split across lines","Verify with `kops get cluster -oyaml` that zones render as full zone names"],"exampleFix":"// before\nzones: [\"a\", \"b\"]\n// after\nzones: [\"us-east-1a\", \"us-east-1b\"]","handlingStrategy":"validation","validationCode":"var awsZoneRe = regexp.MustCompile(`^[a-z]{2}(-gov)?-[a-z]+-\\d[a-z]$`)\nfunc validZone(z string) bool { return awsZoneRe.MatchString(z) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use full AZ names (us-east-1a) everywhere; never bare suffixes","Quote YAML values to avoid truncation/splitting","Lint zones against `aws ec2 describe-availability-zones`"],"tags":["aws","zone","validation","cluster-spec"],"backgroundTag":"invalid-aws-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"}