kubernetes/kops · error
could not determine any subnets for InstanceGroup %q; subnet
Error message
could not determine any subnets for InstanceGroup %q; subnets was %s
What it means
karpenterAssociatePublicIP resolves the subnets of a Karpenter-managed InstanceGroup to decide whether instances get a public IP. It calls GatherSubnets; when the result is empty it cannot classify the InstanceGroup, so it fails with this error. The error message includes the InstanceGroup name and its raw Spec.Subnets list for diagnosis.
Source
Thrown at upup/pkg/fi/cloudup/template_functions_karpenter.go:491
}
tokens := strings.SplitN(image, "/", 2)
if len(tokens) == 1 {
return []karpenterAMITerm{{Name: image, Owner: "self"}}, nil
}
if tokens[0] == "" || tokens[1] == "" {
return nil, fmt.Errorf("image %q must be ami-*, ssm:<parameter>, <name>, or <owner>/<name>", image)
}
return []karpenterAMITerm{{Owner: awsup.ResolveImageOwnerAlias(tokens[0]), Name: tokens[1]}}, nil
}
func (tf *TemplateFunctions) karpenterAssociatePublicIP(ig *kops.InstanceGroup) (*bool, error) {
subnets, err := tf.GatherSubnets(ig)
if err != nil {
return nil, err
}
if len(subnets) == 0 {
return nil, fmt.Errorf("could not determine any subnets for InstanceGroup %q; subnets was %s", ig.Name, ig.Spec.Subnets)
}
switch subnets[0].Type {
case kops.SubnetTypePublic, kops.SubnetTypeUtility:
if ig.Spec.AssociatePublicIP != nil {
return ig.Spec.AssociatePublicIP, nil
}
return new(true), nil
case kops.SubnetTypeDualStack, kops.SubnetTypePrivate:
return new(false), nil
default:
return nil, fmt.Errorf("unknown subnet type %q for InstanceGroup %q", subnets[0].Type, ig.Name)
}
}
func (tf *TemplateFunctions) karpenterRequirements(ig *kops.InstanceGroup) []karpenterRequirement {
requirements := []karpenterRequirement{
{View on GitHub (pinned to 4c8573c808)
Solutions
- Set spec.subnets on the InstanceGroup to valid cluster subnet names (e.g. `subnets: [us-east-1a]`) and re-run kops update.
- Verify the listed subnet names exist in the cluster spec (cluster.spec.subnets) and match exactly (name/zone).
- If the IG is auto-generated by Karpenter integration, ensure the cluster spec subnets are populated before applying.
- Run `kops get instancegroups` / `kops get cluster -o yaml` to confirm subnet wiring.
Example fix
// before spec: subnets: [] // after spec: subnets: - us-east-1a
Defensive patterns
Strategy: validation
Validate before calling
igName := ig.Name
if len(ig.Spec.Subnets) == 0 {
return fmt.Errorf("instance group %q has no subnets; set spec.subnets to cluster subnet names", igName)
} Type guard
func hasSubnets(ig *kops.InstanceGroup) bool {
return ig != nil && len(ig.Spec.Subnets) > 0
} Prevention
- Always set spec.subnets on every InstanceGroup, including Karpenter-managed ones.
- Validate that IG subnet names match cluster.spec.subnets names before `kops update`.
- Run `kops validate cluster` after config edits and before applying.
- Lint cluster YAML against the kops API schema for your kOps version.
When it happens
Trigger: kOps apply/build of a cluster containing a Karpenter EC2NodeClass whose associated InstanceGroup has an empty (or effectively unresolvable) Spec.Subnets list, or subnets that GatherSubnets cannot match against the cluster's defined subnets.
Common situations: NodeTemplates/InstanceGroups created without a `subnets` field; subnets referencing names/zones not present in the cluster spec; Karpenter generated IGs that bypass normal subnet assignment; partial cluster configs migrated between kOps versions.
Related errors
- error subnets must exist in the cluster
- error instance group cannot span public and private subnets
- no subnets found in cluster %q
- invalid EtcdClusterSpec (expected two tokens): %q
- invalid EtcdClusterSpec (member not found in all nodes): %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/dfdb9ed56d8183b4.
Report an issue: GitHub.