{"record":{"id":"d53e5da99da39af6","repo":"kubernetes/kops","slug":"cannot-determine-role-for-instance-group-v","errorCode":null,"errorMessage":"cannot determine role for instance group: %v","messagePattern":"cannot determine role for instance group: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodemodel/nodeupconfigbuilder.go","lineNumber":185,"sourceCode":"\t\tetcdManifests:              etcdManifests,\n\t\timages:                     images,\n\t\tencryptionConfigSecretHash: encryptionConfigSecretHash,\n\t}\n\n\treturn &configBuilder, nil\n}\n\n// BuildConfig returns the NodeUp config and auxiliary config.\nfunc (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, wellKnownAddresses model.WellKnownAddresses, keysets map[string]*fi.Keyset) (*nodeup.Config, *nodeup.BootConfig, error) {\n\tcluster := n.cluster\n\n\tif ig == nil {\n\t\treturn nil, nil, fmt.Errorf(\"instanceGroup cannot be nil\")\n\t}\n\n\trole := ig.Spec.Role\n\tif role == \"\" {\n\t\treturn nil, nil, fmt.Errorf(\"cannot determine role for instance group: %v\", ig.ObjectMeta.Name)\n\t}\n\n\tisMaster := role.HasControlPlane()\n\thasAPIServer := isMaster || role.HasAPIServer()\n\n\tconfig, bootConfig := nodeup.NewConfig(cluster, ig)\n\n\tigModel, err := kopsmodel.ForInstanceGroup(cluster, ig)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"building instance group model: %w\", err)\n\t}\n\n\tif !hasAPIServer && n.assetBuilder.KubeletSupportedVersion != \"\" {\n\t\t// Set kubernetes version to avoid spurious rolling-update\n\t\tconfig.KubernetesVersion = n.assetBuilder.KubeletSupportedVersion\n\n\t\t// TODO: Rename KubernetesVersion to ControlPlaneVersion\n","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodemodel/nodeupconfigbuilder.go#L167-L203","documentation":"After the nil check, BuildConfig reads ig.Spec.Role to branch control-plane vs node behavior. An empty role means the InstanceGroup spec is incomplete; the role cannot be determined so config building aborts with the group's name in the message.","triggerScenarios":"An InstanceGroup with spec.role absent/empty is passed to BuildConfig during nodeup config generation.","commonSituations":"Hand-edited or partially migrated InstanceGroup manifests missing role; cluster created by tooling that omitted the field; schema drift between kOps versions.","solutions":["Set ig.Spec.Role (ControlPlane/Master, Node, Bastion) on the instance group before building config","Recreate the instance group via 'kops create ig' so defaults are applied","Validate the cluster spec (kops validate / kops replace -f) to catch empty roles early"],"exampleFix":"// before\nmetadata:\n  name: nodes\nspec: {} // role missing\n// after\nmetadata:\n  name: nodes\nspec:\n  role: Node","handlingStrategy":"validation","validationCode":"if ig == nil || ig.Spec.Role == \"\" {\n    return fmt.Errorf(\"instance group %v missing spec.role\", ig.ObjectMeta.Name)\n}","typeGuard":"func roleSet(ig *kops.InstanceGroup) bool {\n    return ig != nil && ig.Spec.Role != \"\"\n}","tryCatchPattern":null,"preventionTips":["Always specify spec.role in IG YAML (ControlPlane/Node/Bastion)","Apply IGs through kops CLI rather than raw edits so defaults populate","Lint cluster specs for empty role fields"],"tags":["instancegroup","role","nodeup"],"backgroundTag":"missing-instance-group-role","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"}