kubernetes/kops · error
unhandled bastion LoadBalancer type %q
Error message
unhandled bastion LoadBalancer type %q
What it means
kops's BastionModelBuilder.Build translates the cluster spec's bastion load balancer type (spec.networking.topology.bastion.loadBalancer.type) into an ELB/NLB scheme string. Only "internal" and "public" are recognized; any other value (including an empty string when the surrounding block expected one to be defaulted) makes the builder abort cluster rendering with this error. It is a spec-validation guard inside the AWS model build phase.
Source
Thrown at pkg/model/awsmodel/bastion.go:112
Egress: new(true),
IPv6CIDR: new("::/0"),
}
AddDirectionalGroupRule(c, t)
}
}
var bastionLoadBalancerType kops.LoadBalancerType
{
// Check if we requested a public or internal NLB
if b.Cluster.Spec.Networking.Topology != nil && b.Cluster.Spec.Networking.Topology.Bastion != nil && b.Cluster.Spec.Networking.Topology.Bastion.LoadBalancer != nil {
if b.Cluster.Spec.Networking.Topology.Bastion.LoadBalancer.Type != "" {
switch b.Cluster.Spec.Networking.Topology.Bastion.LoadBalancer.Type {
case kops.LoadBalancerTypeInternal:
bastionLoadBalancerType = "Internal"
case kops.LoadBalancerTypePublic:
bastionLoadBalancerType = "Public"
default:
return fmt.Errorf("unhandled bastion LoadBalancer type %q", b.Cluster.Spec.Networking.Topology.Bastion.LoadBalancer.Type)
}
} else {
// Default to Public
b.Cluster.Spec.Networking.Topology.Bastion.LoadBalancer.Type = kops.LoadBalancerTypePublic
bastionLoadBalancerType = "Public"
}
} else {
// Default to Public
bastionLoadBalancerType = "Public"
}
}
// Allow bastion nodes to SSH to control plane
for _, src := range bastionGroups {
for _, dest := range masterGroups {
t := &awstasks.SecurityGroupRule{
Name: new("bastion-to-master-ssh" + JoinSuffixes(src, dest)),
Lifecycle: b.SecurityLifecycle,View on GitHub (pinned to 4c8573c808)
Solutions
- Set spec.networking.topology.bastion.loadBalancer.type to exactly "internal" or "public" in the cluster manifest
- Remove the loadBalancer.type field entirely so the builder defaults it to "public"
- Run `kops edit cluster` (or the editor of your manifest) and fix casing/typos, then re-run `kops update cluster`
Example fix
// before (cluster.yaml)
topology:
bastion:
loadBalancer:
type: Internal
// after
topology:
bastion:
loadBalancer:
type: internal Defensive patterns
Strategy: validation
Validate before calling
t := cluster.Spec.Networking.Topology.Bastion.LoadBalancer.Type
if t != "" && t != kops.LoadBalancerTypeInternal && t != kops.LoadBalancerTypePublic {
return fmt.Errorf("invalid bastion loadBalancer.type %q: must be \"internal\" or \"public\"", t)
} Type guard
func validBastionLBType(t kops.LoadBalancerType) bool {
return t == kops.LoadBalancerTypeInternal || t == kops.LoadBalancerTypePublic
} Try / catch
if err := buildModel(ctx); err != nil {
if strings.Contains(err.Error(), "unhandled bastion LoadBalancer type") {
return fmt.Errorf("fix spec.networking.topology.bastion.loadBalancer.type (internal|public): %w", err)
}
return err
} Prevention
- Use `kops edit cluster` instead of hand-editing YAML so defaulting/validation runs
- Always use lowercase enum values (internal/public)
- Omit loadBalancer.type to accept the default (public)
- Run `kops validate cluster` or a dry-run before applying
When it happens
Trigger: Running `kops update cluster` (or `kops create cluster --bastion`) where spec.networking.topology.bastion.loadBalancer.type is set to anything other than "internal" or "public" — e.g. a typo like "Internal", "private", or an empty string that bypassed the defaulting branch.
Common situations: Hand-edited cluster manifests, YAML migrated from another tool or older kops version with a now-invalid value, case-sensitivity mistakes (value must be lowercase), or automation templates injecting a wrong default.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- subnet %q had unknown type %q
- error finding aws DNSName: %v
- adding key to SSH agent: %w
- error getting ingress status: %v
- unable to determine IP address for kube-apiserver
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/e8c5bd8b29f9ae8c.
Report an issue: GitHub.