{"record":{"id":"73852e8baff4bc1b","repo":"kubernetes/kops","slug":"unhandled-role-q","errorCode":null,"errorMessage":"unhandled role %q","messagePattern":"unhandled role %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awsup/aws_cloud.go","lineNumber":1994,"sourceCode":"\tcase ig.Spec.Role.HasNode() || ig.Spec.Role.IsControlPlaneType():\n\t\t// t3.medium is the cheapest instance with 4GB of mem, unlimited by default, fast and has decent network\n\t\t// c5.large and c4.large are a good second option in case t3.medium is not available in the AZ\n\t\tcandidates = []ec2types.InstanceType{\n\t\t\tec2types.InstanceTypeT3Medium,\n\t\t\tec2types.InstanceTypeC5Large,\n\t\t\tec2types.InstanceTypeC4Large,\n\t\t\tec2types.InstanceTypeT4gMedium,\n\t\t}\n\n\tcase ig.Spec.Role.HasBastion():\n\t\tcandidates = []ec2types.InstanceType{\n\t\t\tec2types.InstanceTypeT3Micro,\n\t\t\tec2types.InstanceTypeT2Micro,\n\t\t\tec2types.InstanceTypeT4gMicro,\n\t\t}\n\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"unhandled role %q\", ig.Spec.Role)\n\t}\n\n\timageArch := ec2types.ArchitectureTypeX8664\n\tif imageInfo, err := c.ResolveImage(ig.Spec.Image); err == nil {\n\t\timageArch = ec2types.ArchitectureType(imageInfo.Architecture)\n\t}\n\n\t// Find the AZs the InstanceGroup targets\n\tigZones, err := model.FindZonesForInstanceGroup(cluster, ig)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tigZonesSet := sets.NewString(igZones...)\n\n\t// TODO: Validate that instance type exists in all AZs, but skip AZs that don't support any VPC stuff\n\tvar reasons []string\n\tfor _, instanceType := range candidates {\n\t\tif strings.HasPrefix(string(instanceType), \"t4g\") {","sourceCodeStart":1976,"sourceCodeEnd":2012,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awsup/aws_cloud.go#L1976-L2012","documentation":"The function that recommends a default machine image/instance-type path per instance group has an exhaustive switch on ig.Spec.Role (kops InstanceGroupRole: ControlPlane, Node, Bastion, etc.). When a role value falls outside the handled cases, it returns 'unhandled role %q'. This guards against new or invalid roles being silently assigned wrong defaults.","triggerScenarios":"An instance group's spec.role is a value the switch doesn't handle — e.g. a kops version where a new role (like 'APIServer' or 'WarmPool'-related roles) exists but this code predates it, a typo'd/empty role in a hand-edited cluster spec, or a role that only applies to some clouds being used on AWS.","commonSituations":"Hand-editing the cluster manifest and setting role to an invalid lowercase string; using a newer kops CLI with an older controller/library build (or vice versa); copying an instance group from another provider (e.g. GCE-specific role) into an AWS cluster.","solutions":["Check the instance group's role value: kops get ig <name> -o yaml and confirm spec.role is one of ControlPlane, Node, Bastion (or apiserver-managed equivalents).","Fix typos/casing in the cluster spec and run kops update cluster.","Align kops versions — upgrade or downgrade so the binary and cluster spec use the same role vocabulary.","If a genuinely new role was added upstream, update the switch statement to handle it (patch aws_cloud.go)."],"exampleFix":"// before\ncase kops.InstanceGroupRoleNode:\n    ...\ndefault:\n    return \"\", fmt.Errorf(\"unhandled role %q\", ig.Spec.Role)\n// after: handle the new role\ncase kops.InstanceGroupRoleControlPlane, kops.InstanceGroupRoleNode, kops.InstanceGroupRoleBastion:\n    ...","handlingStrategy":"validation","validationCode":"valid := map[kops.InstanceGroupRole]bool{\n    kops.InstanceGroupRoleControlPlane: true,\n    kops.InstanceGroupRoleNode:         true,\n    kops.InstanceGroupRoleBastion:      true,\n}\nif !valid[ig.Spec.Role] {\n    return fmt.Errorf(\"invalid instance group role %q; must be ControlPlane, Node, or Bastion\", ig.Spec.Role)\n}","typeGuard":"func isKnownInstanceGroupRole(r kops.InstanceGroupRole) bool {\n    switch r {\n    case kops.InstanceGroupRoleControlPlane, kops.InstanceGroupRoleNode, kops.InstanceGroupRoleBastion:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Never hand-edit spec.role values; use 'kops create ig' so the CLI validates the role.","Keep the kops binary and cluster spec versions in sync.","Validate manifests with 'kops replace -f manifest.yaml --dry-run' before applying.","When adding a new InstanceGroupRole upstream, audit all switch statements over Role."],"tags":["kops","instance-group","config-validation","switch-case"],"backgroundTag":"unhandled-enum-value","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"}