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

  1. List pools (`openstack loadbalancer pool list`) and delete or rename the duplicate pool sharing the name
  2. Prefer sharing one OpenStack project per cluster so names cannot collide across clusters
  3. Set the pool ID explicitly in the task spec so the filter resolves to a unique pool
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/5c4ce6ff8b780a16. Report an issue: GitHub.