kubernetes/kops · error

found multiple monitors with name: %s

Error message

found multiple monitors with name: %s

What it means

PoolMonitor.Find lists Octavia health monitors for the referenced pool and requires at most one match. When more than one monitor with the same name is found, kOps cannot determine which is the managed one and returns this error instead of guessing.

Source

Thrown at upup/pkg/fi/cloudup/openstacktasks/poolmonitor.go:68

	return p.ID
}

func (p *PoolMonitor) Find(context *fi.CloudupContext) (*PoolMonitor, error) {
	cloud := context.T.Cloud.(openstack.OpenstackCloud)

	opt := monitors.ListOpts{
		Name:   fi.ValueOf(p.Name),
		PoolID: fi.ValueOf(p.Pool.ID),
	}

	rs, err := cloud.ListMonitors(opt)
	if err != nil {
		return nil, err
	}
	if len(rs) == 0 {
		return nil, nil
	} else if len(rs) != 1 {
		return nil, fmt.Errorf("found multiple monitors with name: %s", fi.ValueOf(p.Name))
	}
	found := rs[0]
	actual := &PoolMonitor{
		ID:        new(found.ID),
		Name:      new(found.Name),
		Pool:      p.Pool,
		Lifecycle: p.Lifecycle,
	}
	p.ID = actual.ID
	return actual, nil
}

func (p *PoolMonitor) Run(context *fi.CloudupContext) error {
	return fi.CloudupDefaultDeltaRunMethod(p, context)
}

func (_ *PoolMonitor) CheckChanges(a, e, changes *PoolMonitor) error {
	if a == nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. List monitors (`openstack loadbalancer healthmonitor list`) and delete all but one with that name
  2. Keep one OpenStack project per cluster to avoid name collisions between clusters
  3. Re-run `kops update cluster` after cleanup so Find matches exactly one monitor
  4. Avoid manually creating monitors with names that kops manages

Example fix

// before: two monitors named 'api-monitor' on the pool
openstack loadbalancer healthmonitor delete <duplicate-id>
// after: single monitor remains and reconcile proceeds
Defensive patterns

Strategy: validation

Validate before calling

// detect duplicate monitors before reconcile
cmd := exec.Command("openstack", "loadbalancer", "healthmonitor", "list")
out, _ := cmd.Output()
if bytes.Count(out, []byte(monitorName)) > 1 {
	return fmt.Errorf("duplicate monitor %s; remove extras", monitorName)
}

Type guard

func uniqueMonitors(rs []monitors.Monitor) (*monitors.Monitor, error) {
	if len(rs) == 0 { return nil, nil }
	if len(rs) == 1 { return &rs[0], nil }
	return nil, fmt.Errorf("found %d monitors with same name", len(rs))
}

Try / catch

actual, err := task.Find(ctx)
if err != nil && strings.Contains(err.Error(), "found multiple monitors") {
	// list monitors, delete duplicates, then retry reconcile
}

Prevention

When it happens

Trigger: Listing monitors for the pool returns len(rs) != 1 with >1 result: duplicate health monitors were created on the pool by repeated manual creation or overlapping kops runs against the same project, all sharing the pool monitor's name.

Common situations: An earlier aborted update left a monitor behind and a retry created another; an operator manually added a monitor with the same name for testing; two clusters in one project producing identically named monitors on shared pools.

Related errors


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