kubernetes/kops · error
cannot find subnet %q (declared in instance group %q, not fo
Error message
cannot find subnet %q (declared in instance group %q, not found in cluster)
What it means
FindZonesForInstanceGroup resolves the zones for an instance group by combining ig.Spec.Zones with the zones of each subnet named in ig.Spec.Subnets. If a subnet name listed in the instance group does not match any subnet declared in the cluster spec, FindSubnet returns nil and this error is thrown. It is a configuration consistency check: the cluster spec is the source of truth for subnets.
Source
Thrown at pkg/apis/kops/model/utils.go:42
)
// FindSubnet returns the subnet with the specified name, or returns nil
func FindSubnet(c *kops.Cluster, subnetName string) *kops.ClusterSubnetSpec {
for _, subnet := range c.Spec.Networking.Subnets {
if subnet.Name == subnetName {
return &subnet
}
}
return nil
}
// FindZonesForInstanceGroup computes the zones for an instance group, which are the zones directly declared in the InstanceGroup, or the subnet zones
func FindZonesForInstanceGroup(c *kops.Cluster, ig *kops.InstanceGroup) ([]string, error) {
zones := sets.NewString(ig.Spec.Zones...)
for _, subnetName := range ig.Spec.Subnets {
subnet := FindSubnet(c, subnetName)
if subnet == nil {
return nil, fmt.Errorf("cannot find subnet %q (declared in instance group %q, not found in cluster)", subnetName, ig.ObjectMeta.Name)
}
if subnet.Zone != "" {
zones.Insert(subnet.Zone)
}
}
return zones.List(), nil
}
View on GitHub (pinned to 4c8573c808)
Solutions
- Compare ig.Spec.Subnets entries against c.Spec.Subnets names and correct the subnet name in the instance group spec.
- Add the missing subnet to the cluster spec (c.Spec.Subnets) if it was removed or never declared.
- Use `kops get ig <name> -o yaml` to inspect the exact subnet names kOps expects, and align the IG with them.
- If constructing Cluster/InstanceGroup programmatically, validate subnet names with kops.FindSubnet(c, name) before building.
Example fix
// before (instance group yaml)
metadata:
name: nodes
spec:
subnets:
- utility-us-east-1b # not declared in cluster spec
// after
spec:
subnets:
- us-east-1b # matches a subnet in cluster.spec.subnets Defensive patterns
Strategy: validation
Validate before calling
func validateIGSubnets(c *kops.Cluster, ig *kops.InstanceGroup) error {
known := map[string]bool{}
for _, s := range c.Spec.Subnets {
known[s.Name] = true
}
for _, n := range ig.Spec.Subnets {
if !known[n] {
return fmt.Errorf("IG %q references undeclared subnet %q", ig.Name, n)
}
}
return nil
} Try / catch
zones, err := kops.FindZonesForInstanceGroup(cluster, ig)
if err != nil {
if strings.Contains(err.Error(), "cannot find subnet") {
// fix IG subnets or cluster spec before retrying
}
return err
} Prevention
- Always declare subnets in cluster.spec.subnets first, then reference them by exact name in instance groups.
- Never hand-edit subnet names; regenerate IGs from the cluster spec.
- Run `kops validate cluster` / `kops create -f --dry-run` before applying.
- When copying IGs between clusters, re-map subnet names to the target cluster's topology.
When it happens
Trigger: Calling FindZonesForInstanceGroup (directly, or indirectly via Build, DefaultInstanceType, or setupControlPlane) with an ig whose Spec.Subnets contains a name not present in c.Spec.Subnets — e.g. 'utility-us-east-1a' vs 'us-east-1a' mismatch, typo, renamed subnet, or the cluster object passed is not the one the subnets were declared on.
Common situations: Hand-edited cluster.yaml where the instance group references a subnet removed or renamed; generating instance groups from a template with hard-coded subnet names; passing a partially-populated Cluster object to the model builder; copying an IG from another cluster whose subnet topology differs.
Related errors
- found multiple instance groups matching MIG %q
- subnet %q has unknown type %q
- invalid base channel location: %q
- error parsing Kubernetes version %q: %v
- error parsing configuration: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/7859feeb0dc24660.
Report an issue: GitHub.