kubernetes/kops · error
found multiple pools with name: %s
Error message
found multiple pools with name: %s
What it means
PoolAssociation.Find lists Octavia pools filtered by the desired pool name/ID and requires exactly one match to build the actual state. If the filtered list returns more than one pool, kOps refuses to guess and returns this error, because pool identity is resolved by name.
Source
Thrown at upup/pkg/fi/cloudup/openstacktasks/poolassociation.go:82
return s.ID
}
func (p *PoolAssociation) Find(context *fi.CloudupContext) (*PoolAssociation, error) {
cloud := context.T.Cloud.(openstack.OpenstackCloud)
opt := v2pools.ListOpts{
Name: fi.ValueOf(p.Pool.Name),
ID: fi.ValueOf(p.Pool.ID),
}
rs, err := cloud.ListPools(opt)
if err != nil {
return nil, err
}
if rs == nil {
return nil, nil
} else if len(rs) != 1 {
return nil, fmt.Errorf("found multiple pools with name: %s", fi.ValueOf(p.Pool.Name))
}
a := rs[0]
// check is member already created
var found *v2pools.Member
for _, member := range a.Members {
poolMember, err := cloud.GetPoolMember(a.ID, member.ID)
if err != nil {
return nil, err
}
if fi.ValueOf(p.Name) == poolMember.Name {
found = poolMember
break
}
}
// if not found it is created by returning nil, nil
// this is needed for instance in initial installation
if found == nil {View on GitHub (pinned to 4c8573c808)
Solutions
- List pools (`openstack loadbalancer pool list`) and delete or rename the duplicate pool sharing the name
- Prefer sharing one OpenStack project per cluster so names cannot collide across clusters
- Set the pool ID explicitly in the task spec so the filter resolves to a unique pool
- Re-run the kops update after cleanup; Find will then match exactly one pool
Example fix
// before: two pools named 'api-pool' in one project openstack loadbalancer pool delete <stale-pool-id> // after: only one pool with the desired name remains
Defensive patterns
Strategy: validation
Validate before calling
// detect ambiguity before Find
cmd := exec.Command("openstack", "loadbalancer", "pool", "list", "--name", poolName)
out, _ := cmd.Output()
count := bytes.Count(out, []byte("\n"))
if count > 1 { return fmt.Errorf("duplicate pool %s exists; delete the stale one first", poolName) } Type guard
func uniquePools(rs []v2pools.Pool) (*v2pools.Pool, error) {
switch len(rs) {
case 0:
return nil, nil
case 1:
return &rs[0], nil
default:
return nil, fmt.Errorf("found %d pools with same name", len(rs))
}
} Try / catch
actual, err := task.Find(ctx)
if err != nil && strings.Contains(err.Error(), "found multiple pools") {
// list and delete duplicates, then retry reconcile
} Prevention
- Run one kops cluster per OpenStack project
- Never manually create pools with names kops manages
- Clean up resources after aborted updates before retrying
When it happens
Trigger: cloud.ListPools with ListOpts{Name, ID} returns len(rs) != 1 and > 1: two Octavia loadbalancer pools share the same name in the project (e.g. duplicated by a previous partial run, manual creation, or cross-project copy).
Common situations: A previous failed `kops update cluster` left duplicate pools; an operator manually created a pool with the same name in the same project; multiple clusters sharing one OpenStack project and identical LB names.
Related errors
- failed to build load balancer client: %w
- error building lb client: %w
- loadbalancer API versions not found
- GetApiIngressStatus: Failed to list openstack loadbalancers:
- error deleting loadbalancer: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/5c4ce6ff8b780a16.
Report an issue: GitHub.