kubernetes/kops · error

unexpected subnet type: for InstanceGroup

Error message

unexpected subnet type: for InstanceGroup %q; type was %s

What it means

buildVMScaleSetTask switches on the resolved subnet's Type (Public/Utility, DualStack, Private) to configure whether the scale set requires a public IP. Any other subnet type reaches the default branch and aborts model building with this error.

Solutions

  1. Set spec.type of the referenced subnet to one of Public, Utility, DualStack, or Private in the cluster spec.
  2. Upgrade kops to a version that recognizes the configured subnet type.
  3. Re-run `kops get cluster -o yaml` and fix any manually edited subnet entries, then `kops update cluster`.

Example fix

// before (cluster spec subnet)
type: ""
// after
type: Private
Defensive patterns

Strategy: validation

Validate before calling

valid := map[kops.SubnetType]bool{kops.SubnetTypePublic: true, kops.SubnetTypeUtility: true, kops.SubnetTypeDualStack: true, kops.SubnetTypePrivate: true}
for _, s := range cluster.Spec.Subnets {
  if !valid[s.Type] {
    return fmt.Errorf("subnet %q has unsupported type %q", s.Name, s.Type)
  }
}

Prevention

When it happens

Trigger: An InstanceGroup on Azure references a subnet whose spec.type is an unrecognized/unset value (e.g. empty string, or a type only valid on other clouds).

Common situations: Subnet type omitted in cluster spec; hand-edited cluster.yaml introducing an invalid type; using a subnet type added by a newer kops version with an older binary (or vice versa).

Related errors


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

Appendix: source

Thrown at pkg/model/azuremodel/vmscaleset.go:170

	if err != nil {
		return nil, err
	}
	if len(subnets) != 1 {
		return nil, fmt.Errorf("expected exactly one subnet for InstanceGroup %q; subnets was %s", ig.Name, ig.Spec.Subnets)
	}
	subnet := subnets[0]
	t.Subnet = b.LinkToAzureSubnet(subnet)

	switch subnet.Type {
	case kops.SubnetTypePublic, kops.SubnetTypeUtility:
		t.RequirePublicIP = new(true)
		if ig.Spec.AssociatePublicIP != nil {
			t.RequirePublicIP = ig.Spec.AssociatePublicIP
		}
	case kops.SubnetTypeDualStack, kops.SubnetTypePrivate:
		t.RequirePublicIP = new(false)
	default:
		return nil, fmt.Errorf("unexpected subnet type: for InstanceGroup %q; type was %s", ig.Name, subnet.Type)
	}

	if ig.Spec.Role.HasControlPlane() && b.Cluster.Spec.API.LoadBalancer != nil {
		t.LoadBalancer = &azuretasks.LoadBalancer{
			Name: to.Ptr(b.NameForLoadBalancer()),
		}
	}

	t.Tags = b.CloudTagsForInstanceGroup(ig)

	return t, nil
}

func getCapacity(spec *kops.InstanceGroupSpec) (*int64, error) {
	// Follow the convention that all other CSPs have.
	minSize := int32(1)
	maxSize := int32(1)
	if spec.MinSize != nil {

View on GitHub (pinned to 4c8573c808)