kubernetes/kops · error
unhandled LoadBalancer type %q
Error message
unhandled LoadBalancer type %q
What it means
APILoadBalancerBuilder.Build in pkg/model/awsmodel builds the AWS load balancer task for the kOps API endpoint. The cluster spec's api.loadBalancer.type is only allowed to be "Internal" or "Public"; any other string makes the builder fail fast with this error rather than silently provisioning the wrong LB type.
Source
Thrown at pkg/model/awsmodel/api_loadbalancer.go:61
// Build is responsible for building the KubeAPI tasks for the aws model
func (b *APILoadBalancerBuilder) Build(c *fi.CloudupModelBuilderContext) error {
// Configuration where an ELB fronts the API
if !b.UseLoadBalancerForAPI() {
return nil
}
lbSpec := b.Cluster.Spec.API.LoadBalancer
if lbSpec == nil {
// Skipping API ELB creation; not requested in Spec
return nil
}
switch lbSpec.Type {
case kops.LoadBalancerTypeInternal, kops.LoadBalancerTypePublic:
// OK
default:
return fmt.Errorf("unhandled LoadBalancer type %q", lbSpec.Type)
}
var nlbSubnetMappings []*awstasks.SubnetMapping
if len(lbSpec.Subnets) != 0 {
// Subnets have been explicitly set
for _, subnet := range lbSpec.Subnets {
for _, clusterSubnet := range b.Cluster.Spec.Networking.Subnets {
if subnet.Name == clusterSubnet.Name {
nlbSubnetMapping := &awstasks.SubnetMapping{
Subnet: b.LinkToSubnet(&clusterSubnet),
}
if subnet.PrivateIPv4Address != nil {
nlbSubnetMapping.PrivateIPv4Address = subnet.PrivateIPv4Address
}
if subnet.AllocationID != nil {
nlbSubnetMapping.AllocationID = subnet.AllocationID
}
nlbSubnetMappings = append(nlbSubnetMappings, nlbSubnetMapping)View on GitHub (pinned to 4c8573c808)
Solutions
- Set api.loadBalancer.type to exactly "Internal" or "Public" in the cluster spec
- Run `kops set cluster` / `kops edit cluster` instead of hand-editing to avoid typos
- Trim whitespace and match case exactly, then `kops update cluster` again
Example fix
# before
api:
loadBalancer:
type: private
# after
api:
loadBalancer:
type: Internal Defensive patterns
Strategy: validation
Validate before calling
lb := cluster.Spec.API.LoadBalancer
if lb != nil && lb.Type != kops.LoadBalancerTypeInternal && lb.Type != kops.LoadBalancerTypePublic {
return fmt.Errorf("api.loadBalancer.type must be Internal or Public, got %q", lb.Type)
} Type guard
func validLBType(t string) bool {
return t == kops.LoadBalancerTypeInternal || t == kops.LoadBalancerTypePublic
} Try / catch
if err := kopsUpdateCluster(cluster); err != nil {
if strings.Contains(err.Error(), "unhandled LoadBalancer type") {
// fix spec.api.loadBalancer.type and retry
}
return err
} Prevention
- Only use the documented values Internal and Public for api.loadBalancer.type
- Edit the cluster via `kops edit cluster` to get spec validation
- Trim whitespace and match capitalization exactly
When it happens
Trigger: Running `kops update cluster` when cluster spec has api.loadBalancer.type set to a value other than Internal/Public (typo like "internal " (trailing space), "private", "external", or mixed case like "PUBLIC").
Common situations: Hand-edited cluster.yaml after upgrade, snippets copied from docs for other clouds, or specs written before validation for this field existed.
Related errors
- subnet %q had unknown type %q
- must configure at least one Node InstanceGroup
- no subnets found in cluster %q
- unhandled bastion LoadBalancer type %q
- subnet %q had unknown type %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/a754eeae2a50881e.
Report an issue: GitHub.