kubernetes/kops · error

applying changes to Router is unsupported: %s

Error message

applying changes to Router is unsupported: %s

What it means

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.

Source

Thrown at upup/pkg/fi/cloudup/gcetasks/router.go:180

			},
		}

		for _, subnet := range e.Subnetworks {
			router.Nats[0].Subnetworks = append(router.Nats[0].Subnetworks, &compute.RouterNatSubnetworkToNat{
				Name:                subnet.URL(project, region),
				SourceIpRangesToNat: []string{subnetNatAllIPRanges},
			})
		}
		op, err := t.Cloud.Compute().Routers().Insert(project, region, router)
		if err != nil {
			return fmt.Errorf("error creating Router: %w", err)
		}
		if err := t.Cloud.WaitForOp(op); err != nil {
			return fmt.Errorf("error waiting for router creation: %w", err)
		}
	} else {
		if !reflect.DeepEqual(changes, &Router{}) {
			return fmt.Errorf("applying changes to Router is unsupported: %s", *e.Name)
		}
	}

	return nil
}

type terraformRouterNat struct {
	Name                          *string                         `cty:"name"`
	Region                        *string                         `cty:"region"`
	Router                        *terraformWriter.Literal        `cty:"router"`
	NATIPAllocateOption           *string                         `cty:"nat_ip_allocate_option"`
	SourceSubnetworkIPRangesToNat *string                         `cty:"source_subnetwork_ip_ranges_to_nat"`
	Subnetworks                   []*terraformRouterNatSubnetwork `cty:"subnetwork"`
}

type terraformRouterNatSubnetwork struct {
	Name                *terraformWriter.Literal `cty:"name"`
	SourceIPRangesToNat []string                 `cty:"source_ip_ranges_to_nat"`

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Identify the drift: compare the router's actual config (`gcloud compute routers describe`) with the desired kOps spec
  2. Delete the drifted router (`gcloud compute routers delete`) and re-run `kops update cluster` so it is recreated from spec
  3. Restore the router to match the kOps model manually if deletion is disruptive
  4. Pin/align the kOps version used to create the cluster with the one performing updates to avoid model-induced diffs

Example fix

// before: kOps cannot update a drifted router; recreate it out-of-band
$ gcloud compute routers delete <router-name> --region <region>
$ kops update cluster <cluster> --yes
// after: router is recreated matching the model
Defensive patterns

Strategy: validation

Validate before calling

// Compare desired vs actual before apply; recreate if drifted
actual := &gcetasks.Router{}
if err := task.Find(context, actual); err != nil { return err }
if !reflect.DeepEqual(changes, &gcetasks.Router{}) {
    fmt.Printf("router %s drifted; delete it before re-running update\n", *task.Name)
}

Type guard

func routerNeedsRecreation(changes *gcetasks.Router) bool {
    return !reflect.DeepEqual(changes, &gcetasks.Router{})
}

Try / catch

if err := applyCluster(); err != nil {
    if strings.Contains(err.Error(), "applying changes to Router is unsupported") {
        name := extractRouterName(err)
        exec("gcloud", "compute", "routers", "delete", name, "--region", region, "--quiet")
        return applyCluster() // recreate from spec
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/20b868fed3c7c2c6. Report an issue: GitHub.