kubernetes/kops · error

error creating Router: %w

Error message

error creating Router: %w

What it means

This error is returned by the GCE Router task's RenderGCE when the google Compute API call Routers().Insert() fails while kOps tries to create a Cloud Router (used for Cloud NAT) in the target project/region. It wraps the underlying Google API error, so the root cause (quota, permission, invalid config, API error) is in the wrapped %w error. It means the router resource was never created and the apply of this task failed.

Source

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

			Network: e.Network.URL(project),
			Nats: []*compute.RouterNat{
				{
					Name:                          *e.Name,
					NatIpAllocateOption:           *e.NATIPAllocationOption,
					SourceSubnetworkIpRangesToNat: *e.SourceSubnetworkIPRangesToNAT,
				},
			},
		}

		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"`

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped error in the message for the exact Google API cause (permissionDenied, quotaExceeded, notFound, etc.) and address that first
  2. Verify the Compute Engine API is enabled in the project (gcloud services list --enabled | grep compute)
  3. Check the GCE service account has roles/compute.networkAdmin or at least compute.routers.create permission
  4. Confirm the cluster spec's region/network/subnet names are correct and exist in the project
  5. Retry the `kops update cluster` apply if the underlying error was transient (rate limit / backend error)

Example fix

// before (transient API failures abort the apply)
op, err := t.Cloud.Compute().Routers().Insert(project, region, router)
if err != nil {
    return fmt.Errorf("error creating Router: %w", err)
}
// after (retry transient errors with backoff before giving up)
op, err := t.Cloud.Compute().Routers().Insert(project, region, router)
if err != nil {
    if gce.IsRetryable(err) {
        return fi.NewRetryableError(fmt.Errorf("error creating Router: %w", err))
    }
    return fmt.Errorf("error creating Router: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check before apply
if err := checkComputeAPIEnabled(projectID); err != nil { return err }
if _, err := compute.Routers.List(projectID, region).Do(); err != nil {
    return fmt.Errorf("cannot access Routers API in %s: %w", region, err)
}

Type guard

func isPermissionDenied(err error) bool {
    var ge *googleapi.Error
    return errors.As(err, &ge) && (ge.Code == 403 || ge.Code == 401)
}

Try / catch

op, err := cloud.Compute().Routers().Insert(project, region, router)
if err != nil {
    var ge *googleapi.Error
    if errors.As(err, &ge) && ge.Code == 403 {
        return fmt.Errorf("missing compute.routers.create permission: %w", err)
    }
    return fmt.Errorf("error creating Router: %w", err)
}
if err := cloud.WaitForOp(op); err != nil {
    return fmt.Errorf("error waiting for router creation: %w", err)
}

Prevention

When it happens

Trigger: Routers().Insert(project, region, router) returns a non-nil error during `kops update cluster` on GCE: e.g. the compute API is disabled, the service account lacks compute.routers.create, the region is wrong, a router with the same name exists in a conflicting state, or quota/billing issues.

Common situations: New GCE projects where the Compute Engine API was just enabled and propagation is pending; IAM scopes on the node/service account missing compute rights; deploying to a region typo'd in the cluster spec; Google API transient 5xx/rate-limit errors during cluster creation.

Related errors


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