{"record":{"id":"c6e5e4420827b5eb","repo":"kubernetes/kops","slug":"missing-target-for-route","errorCode":null,"errorMessage":"missing target for route","messagePattern":"missing target for route","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/route.go","lineNumber":203,"sourceCode":"\t}\n\treturn nil\n}\n\nfunc (_ *Route) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Route) error {\n\tctx := context.TODO()\n\tif a == nil {\n\t\trequest := &ec2.CreateRouteInput{}\n\t\trequest.RouteTableId = checkNotNil(e.RouteTable.ID)\n\n\t\tif e.CIDR != nil || e.IPv6CIDR != nil {\n\t\t\trequest.DestinationCidrBlock = e.CIDR\n\t\t\trequest.DestinationIpv6CidrBlock = e.IPv6CIDR\n\t\t} else {\n\t\t\tklog.Fatal(\"both CIDR and IPv6CIDR were unexpectedly nil\")\n\t\t}\n\n\t\tif e.EgressOnlyInternetGateway == nil && e.InternetGateway == nil && e.NatGateway == nil && e.TransitGatewayID == nil && e.VPCPeeringConnectionID == nil {\n\t\t\treturn fmt.Errorf(\"missing target for route\")\n\t\t} else if e.EgressOnlyInternetGateway != nil {\n\t\t\trequest.EgressOnlyInternetGatewayId = checkNotNil(e.EgressOnlyInternetGateway.ID)\n\t\t} else if e.InternetGateway != nil {\n\t\t\trequest.GatewayId = checkNotNil(e.InternetGateway.ID)\n\t\t} else if e.NatGateway != nil {\n\t\t\trequest.NatGatewayId = checkNotNil(e.NatGateway.ID)\n\t\t} else if e.TransitGatewayID != nil {\n\t\t\trequest.TransitGatewayId = e.TransitGatewayID\n\t\t} else if e.VPCPeeringConnectionID != nil {\n\t\t\trequest.VpcPeeringConnectionId = e.VPCPeeringConnectionID\n\t\t}\n\n\t\tif e.Instance != nil {\n\t\t\trequest.InstanceId = checkNotNil(e.Instance.ID)\n\t\t}\n\n\t\tklog.V(2).Infof(\"Creating Route with RouteTable:%q CIDR:%q IPv6CIDR:%q\",\n\t\t\taws.ToString(e.RouteTable.ID), aws.ToString(e.CIDR), aws.ToString(e.IPv6CIDR))","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/route.go#L185-L221","documentation":"This is a runtime guard in the Route task's RenderAWS (create path): when building the CreateRouteInput, none of the target fields (EgressOnlyInternetGateway, InternetGateway, NatGateway, TransitGatewayID, VPCPeeringConnectionID) are set, so the request cannot be populated. Normally CheckChanges catches this earlier; reaching it means the task bypassed validation or the field was mutated.","triggerScenarios":"RenderAWS executing with all route targets nil while CIDR or IPv6CIDR is set — e.g. validation skipped or task state changed between check and apply.","commonSituations":"Programmatic task construction that skips CheckChanges; applying a partially deserialized manifest where target fields were dropped by unknown-field pruning.","solutions":["Ensure one route target field is populated in the cluster spec","Run kops with current version to guarantee CheckChanges runs before RenderAWS","Check that no newer kops removed/renamed the target field in your manifest, silently dropping it"],"exampleFix":"// before\nroute:\n  cidr: 10.0.0.0/8\n// after\nroute:\n  cidr: 10.0.0.0/8\n  natGateway: nat-0abc123","handlingStrategy":"validation","validationCode":"// same target check as CheckChanges, run before constructing the task\nif !hasRouteTarget(route) { return errors.New(\"missing target for route\") }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always construct Route tasks through the normal kops apply flow so CheckChanges runs first","Do not mutate task fields programmatically after validation"],"tags":["aws","route","validation","missing-target"],"backgroundTag":"missing-required-argument","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}