{"record":{"id":"453302cd714c6e96","repo":"kubernetes/kops","slug":"unable-to-tag-route-table-v","errorCode":null,"errorMessage":"unable to tag route table %v","messagePattern":"unable to tag route table (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/natgateway.go","lineNumber":361,"sourceCode":"\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\")\n\t\t}\n\t\tklog.V(2).Infof(\"tagging route table %s to track shared NGW\", fi.ValueOf(e.AssociatedRouteTable.ID))\n\t\terr = t.AddAWSTags(fi.ValueOf(e.AssociatedRouteTable.ID), tags)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"unable to tag route table %v\", err)\n\t\t}\n\t}\n\n\treturn nil\n}\n\ntype terraformNATGateway struct {\n\tAllocationID *terraformWriter.Literal `cty:\"allocation_id\"`\n\tSubnetID     *terraformWriter.Literal `cty:\"subnet_id\"`\n\tTag          map[string]string        `cty:\"tags\"`\n}\n\nfunc (_ *NatGateway) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *NatGateway) error {\n\tif fi.ValueOf(e.Shared) {\n\t\tif e.ID == nil {\n\t\t\treturn fmt.Errorf(\"ID must be set, if NatGateway is shared: %s\", e)\n\t\t}\n","sourceCodeStart":343,"sourceCodeEnd":379,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/natgateway.go#L343-L379","documentation":"After tagging the subnet, a shared NAT gateway also tags its associated route table via AddAWSTags(fi.ValueOf(e.AssociatedRouteTable.ID), tags). If the AWS CreateTags call for the route table fails, RenderAWS wraps it as \"unable to tag route table %v\".","triggerScenarios":"AddAWSTags on the route table returns an error during RenderAWS of a shared NGW — InvalidRouteTableID.NotFound, ec2:CreateTags authorization failure, or AWS throttling.","commonSituations":"IAM policy not allowing ec2:CreateTags on route tables; route table deleted externally; transient AWS API errors during apply.","solutions":["Inspect the wrapped cause: fix IAM (allow ec2:CreateTags on route-table ARNs) if UnauthorizedOperation","If the route table is not found, correct the AssociatedRouteTable ID in the spec and re-apply","Retry on transient throttling errors"],"exampleFix":"// before\npolicy without route-table tag permission\n// after\nallow ec2:CreateTags on arn:aws:ec2:*:*:route-table/*","handlingStrategy":"retry","validationCode":"_, err := cloud.EC2().DescribeRouteTables(&ec2.DescribeRouteTablesInput{RouteTableIds: []string{*rtID}})\nif err != nil { return fmt.Errorf(\"route table %s missing: %w\", *rtID, err) }","typeGuard":null,"tryCatchPattern":"if err != nil {\n    var awsErr smithy.APIError\n    if errors.As(err, &awsErr) && awsErr.ErrorCode() == \"UnauthorizedOperation\" {\n        // fix IAM: ec2:CreateTags on route-table ARNs\n    }\n}","preventionTips":["Allow ec2:CreateTags on route-table ARNs in IAM","Verify the route table ID exists before applying","Retry transient throttling"],"tags":["aws","nat-gateway","route-table","tagging"],"backgroundTag":"aws-tag-permission-denied","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"}