{"record":{"id":"20b868fed3c7c2c6","repo":"kubernetes/kops","slug":"applying-changes-to-router-is-unsupported-s","errorCode":null,"errorMessage":"applying changes to Router is unsupported: %s","messagePattern":"applying changes to Router is unsupported: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gcetasks/router.go","lineNumber":180,"sourceCode":"\t\t\t},\n\t\t}\n\n\t\tfor _, subnet := range e.Subnetworks {\n\t\t\trouter.Nats[0].Subnetworks = append(router.Nats[0].Subnetworks, &compute.RouterNatSubnetworkToNat{\n\t\t\t\tName:                subnet.URL(project, region),\n\t\t\t\tSourceIpRangesToNat: []string{subnetNatAllIPRanges},\n\t\t\t})\n\t\t}\n\t\top, err := t.Cloud.Compute().Routers().Insert(project, region, router)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error creating Router: %w\", err)\n\t\t}\n\t\tif err := t.Cloud.WaitForOp(op); err != nil {\n\t\t\treturn fmt.Errorf(\"error waiting for router creation: %w\", err)\n\t\t}\n\t} else {\n\t\tif !reflect.DeepEqual(changes, &Router{}) {\n\t\t\treturn fmt.Errorf(\"applying changes to Router is unsupported: %s\", *e.Name)\n\t\t}\n\t}\n\n\treturn nil\n}\n\ntype terraformRouterNat struct {\n\tName                          *string                         `cty:\"name\"`\n\tRegion                        *string                         `cty:\"region\"`\n\tRouter                        *terraformWriter.Literal        `cty:\"router\"`\n\tNATIPAllocateOption           *string                         `cty:\"nat_ip_allocate_option\"`\n\tSourceSubnetworkIPRangesToNat *string                         `cty:\"source_subnetwork_ip_ranges_to_nat\"`\n\tSubnetworks                   []*terraformRouterNatSubnetwork `cty:\"subnetwork\"`\n}\n\ntype terraformRouterNatSubnetwork struct {\n\tName                *terraformWriter.Literal `cty:\"name\"`\n\tSourceIPRangesToNat []string                 `cty:\"source_ip_ranges_to_nat\"`","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gcetasks/router.go#L162-L198","documentation":"RenderGCE raises this when a Router task runs in 'update' mode (the router already exists) but the computed changes are not an empty diff — kOps does not implement in-place updates for GCE Cloud Routers, so any drift is rejected rather than applied. The %s is the router's name.","triggerScenarios":"An existing GCE router's actual state differs from the desired spec (e.g. someone edited the router manually in the console, or the kOps model changed the NAT config between versions), so changes != &Router{} in the else branch.","commonSituations":"Manual modifications of the Cloud Router via gcloud/console outside kOps; upgrading kOps to a version that renders different router fields; clusters imported or created with older kOps model revisions.","solutions":["Identify the drift: compare the router's actual config (`gcloud compute routers describe`) with the desired kOps spec","Delete the drifted router (`gcloud compute routers delete`) and re-run `kops update cluster` so it is recreated from spec","Restore the router to match the kOps model manually if deletion is disruptive","Pin/align the kOps version used to create the cluster with the one performing updates to avoid model-induced diffs"],"exampleFix":"// before: kOps cannot update a drifted router; recreate it out-of-band\n$ gcloud compute routers delete <router-name> --region <region>\n$ kops update cluster <cluster> --yes\n// after: router is recreated matching the model","handlingStrategy":"validation","validationCode":"// Compare desired vs actual before apply; recreate if drifted\nactual := &gcetasks.Router{}\nif err := task.Find(context, actual); err != nil { return err }\nif !reflect.DeepEqual(changes, &gcetasks.Router{}) {\n    fmt.Printf(\"router %s drifted; delete it before re-running update\\n\", *task.Name)\n}","typeGuard":"func routerNeedsRecreation(changes *gcetasks.Router) bool {\n    return !reflect.DeepEqual(changes, &gcetasks.Router{})\n}","tryCatchPattern":"if err := applyCluster(); err != nil {\n    if strings.Contains(err.Error(), \"applying changes to Router is unsupported\") {\n        name := extractRouterName(err)\n        exec(\"gcloud\", \"compute\", \"routers\", \"delete\", name, \"--region\", region, \"--quiet\")\n        return applyCluster() // recreate from spec\n    }\n    return err\n}","preventionTips":["Never edit kOps-managed Cloud Routers via gcloud/console","Use the same kOps version for creation and subsequent updates","Run `kops update cluster` in dry-run to detect drift before apply","Track kOps model changes between upgrades and expect router recreation"],"tags":["gce","networking","router","drift","unsupported-operation"],"backgroundTag":"apply-changes-unsupported","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"}