{"record":{"id":"0b7cbcb13331d5e1","repo":"kubernetes/kops","slug":"subnet-id-not-set-0b7cbc","errorCode":null,"errorMessage":"Subnet ID not set","messagePattern":"Subnet ID not set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/natgateway.go","lineNumber":338,"sourceCode":"\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"Error creating Nat Gateway: %v\", err)\n\t\t}\n\t\te.ID = response.NatGateway.NatGatewayId\n\t\tid = e.ID\n\t} else {\n\t\tid = a.ID\n\t}\n\n\terr := t.AddAWSTags(*e.ID, e.Tags)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to tag NatGateway\")\n\t}\n\n\t// Tag the associated subnet\n\tif e.Subnet == nil {\n\t\treturn fmt.Errorf(\"Subnet not set\")\n\t} else if e.Subnet.ID == nil {\n\t\treturn fmt.Errorf(\"Subnet ID not set\")\n\t}\n\n\t// TODO: AssociatedNatgateway tag is obsolete - we can get from the route table instead\n\ttags := make(map[string]string)\n\ttags[\"AssociatedNatgateway\"] = *id\n\terr = t.AddAWSTags(*e.Subnet.ID, tags)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"unable to tag subnet %v\", err)\n\t}\n\n\t// If this is a shared NGW, we need to tag it\n\t// The tag that implies \"shared\" is `AssociatedNatgateway`=> NGW-ID\n\t// This is better than just a tag that's shared because this lets us create a whitelist of these NGWs\n\t// without doing a bunch more work in `kutil/delete_cluster.go`\n\n\tif fi.ValueOf(e.Shared) {\n\t\tif e.AssociatedRouteTable == nil {\n\t\t\treturn fmt.Errorf(\"AssociatedRouteTable not provided\")","sourceCodeStart":320,"sourceCodeEnd":356,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/natgateway.go#L320-L356","documentation":"In RenderAWS for the NatGateway task, kOps tags the subnet associated with the NAT gateway using AddAWSTags. Before tagging it validates that e.Subnet is set and that its ID is populated. If the subnet exists as a task reference but its AWS ID is nil (not yet resolved), the render aborts with \"Subnet ID not set\".","triggerScenarios":"RenderAWS runs during aws target apply when e.Subnet is non-nil but e.Subnet.ID == nil, typically because the subnet task was never provisioned/lifecycled before the NAT gateway, or the subnet reference came from a shared/imported spec without an ID.","commonSituations":"Cluster spec where a utility subnet references a subnet with an unknown ID; misordered task lifecycle (subnet deferred or omitted); hand-edited cluster spec or terraform import missing the subnet ID.","solutions":["Ensure the Subnet task for this NAT gateway is included in the target and has a resolvable ID (not nil) before the NAT gateway render","Check the cluster spec that the NAT gateway's Subnet field points at a defined, non-shared subnet with an ID","Run kops update with the correct lifecycle so subnet tasks execute before the NAT gateway task","If the subnet is shared, populate its ID explicitly in the spec"],"exampleFix":"// before (task graph omits the subnet the NGW references)\nNatGateway: Subnet: nil-referenced subnet\n// after\nnat.Subnet = fi.WrapSubnet(subnetTask) // subnetTask is a real awstasks.Subnet with a set ID and earlier lifecycle","handlingStrategy":"validation","validationCode":"if nat.Subnet == nil || nat.Subnet.ID == nil {\n    return fmt.Errorf(\"nat gateway %s has no resolvable subnet ID; define/lifecycle the subnet task first\", name)\n}","typeGuard":"func hasSubnetID(s *awstasks.Subnet) bool { return s != nil && s.ID != nil }","tryCatchPattern":null,"preventionTips":["Always define the Subnet task before the NatGateway task that references it","Check `kops update --dry-run` output for unresolved subnet references","Avoid hand-editing subnet IDs out of spec"],"tags":["aws","nat-gateway","subnet","render"],"backgroundTag":"subnet-id-not-set","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"}