{"record":{"id":"c65b5f3c2380999d","repo":"kubernetes/kops","slug":"must-configure-at-least-one-instancegroup","errorCode":null,"errorMessage":"must configure at least one InstanceGroup","messagePattern":"must configure at least one InstanceGroup","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/apis/kops/validation/legacy.go","lineNumber":277,"sourceCode":"\n\tif said.EnableAWSOIDCProvider {\n\t\tenableOIDCField := fieldSpec.Child(\"serviceAccountIssuerDiscovery\", \"enableAWSOIDCProvider\")\n\t\tif discoveryStore == \"\" && discoveryService == nil {\n\t\t\tallErrs = append(allErrs, field.Forbidden(enableOIDCField, \"AWS OIDC Provider requires a discoveryStore or discoveryService to be set\"))\n\t\t}\n\t}\n\n\treturn allErrs\n}\n\n// DeepValidate is responsible for validating the instancegroups within the cluster spec\nfunc DeepValidate(c *kops.Cluster, groups []*kops.InstanceGroup, strict bool, vfsContext *vfs.VFSContext, cloud fi.Cloud) error {\n\tif errs := ValidateCluster(c, strict, vfsContext); len(errs) != 0 {\n\t\treturn errs.ToAggregate()\n\t}\n\n\tif len(groups) == 0 {\n\t\treturn fmt.Errorf(\"must configure at least one InstanceGroup\")\n\t}\n\n\tcontrolPlaneGroupCount := 0\n\tnodeGroupCount := 0\n\tfor _, g := range groups {\n\t\tif g.IsControlPlane() {\n\t\t\tcontrolPlaneGroupCount++\n\t\t} else {\n\t\t\tnodeGroupCount++\n\t\t}\n\t}\n\n\tif controlPlaneGroupCount == 0 {\n\t\treturn fmt.Errorf(\"must configure at least one ControlPlane InstanceGroup\")\n\t}\n\n\tif nodeGroupCount == 0 {\n\t\treturn fmt.Errorf(\"must configure at least one Node InstanceGroup\")","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/apis/kops/validation/legacy.go#L259-L295","documentation":"DeepValidate enforces that a cluster configuration includes at least one InstanceGroup before validating groups individually. kOps clusters cannot run without instance groups since they define the machines running Kubernetes. This error is returned immediately after cluster spec validation passes but the group list is empty.","triggerScenarios":"kops create cluster / kops update cluster / kops create -f cluster.yaml invoked with a Cluster manifest that has zero InstanceGroups, or programmatic use of DeepValidate with an empty groups slice.","commonSituations":"Creating a cluster from a YAML manifest containing only the Cluster object without InstanceGroup documents; a partial file split losing InstanceGroup definitions; CLI flag omission that skips default group creation; API-driven provisioning that forgot to append groups.","solutions":["Add InstanceGroup manifests to the cluster YAML or run kops create ig to define control-plane and node groups","Use 'kops create cluster ...' without suppressing instance-group generation so defaults are created","When using -f, include both Cluster and InstanceGroup documents in the file (or apply them all together)","In code, ensure the groups slice passed to DeepValidate is populated from the parsed manifests"],"exampleFix":"// before (cluster.yaml)\napiVersion: kops.k8s.io/v1alpha2\nkind: Cluster\nmetadata:\n  name: mycluster.example.com\n# no InstanceGroup documents\n// after\napiVersion: kops.k8s.io/v1alpha2\nkind: InstanceGroup\nmetadata:\n  name: control-plane-us-east-1a\n  cluster: mycluster.example.com\nspec:\n  role: ControlPlane\n  machineType: m5.large\n  minSize: 1\n  maxSize: 1","handlingStrategy":"validation","validationCode":"groups, err := configstore.ReadInstanceGroups(vfs.Context, path)\nif err != nil { return err }\nif len(groups) == 0 {\n    return errors.New(\"no InstanceGroups found; run 'kops create ig' or include InstanceGroup docs in your manifest\")\n}\nif err := validation.DeepValidate(cluster, groups, true, vfs.Context, cloud); err != nil { return err }","typeGuard":"func hasInstanceGroups(groups []*kops.InstanceGroup) bool {\n    return len(groups) > 0\n}","tryCatchPattern":"if err := validation.DeepValidate(cluster, groups, strict, vfsContext, cloud); err != nil {\n    if strings.Contains(err.Error(), \"at least one InstanceGroup\") {\n        return fmt.Errorf(\"cluster %s has no instance groups; add control-plane and node groups before updating\", cluster.Name)\n    }\n    return err\n}","preventionTips":["When authoring cluster YAML by hand, always include InstanceGroup documents alongside the Cluster doc","Use 'kops create cluster' to generate a known-good baseline manifest set","List groups with 'kops get ig --name <cluster>' before update to confirm they exist","In tooling, assert len(groups) > 0 before invoking DeepValidate"],"tags":["kops","validation","instance-group","cluster-config"],"backgroundTag":"missing-required-config","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}