cilium/cilium · error

clusterID %d is already used

Error message

clusterID %d is already used

What it means

clusterIDsManager.ReserveClusterID in pkg/clustermesh/common/idsmgr.go:47 rejects a clusterID already held by another remote cluster (m.usedIDs, guarded by mutex). IDs must be globally unique across the mesh; the manager throws this when a second remote connection tries to claim an ID that is currently in use.

Source

Thrown at pkg/clustermesh/common/idsmgr.go:47

	return &clusterIDsManager{
		localClusterID: info.ID,
		usedIDs:        sets.New[uint32](),
	}
}

func (m *clusterIDsManager) ReserveClusterID(clusterID uint32) error {
	if clusterID == types.ClusterIDUnset {
		return fmt.Errorf("clusterID %d is reserved", clusterID)
	}
	if clusterID == m.localClusterID {
		return fmt.Errorf("clusterID %d is assigned to the local cluster", clusterID)
	}

	m.mutex.Lock()
	defer m.mutex.Unlock()

	if m.usedIDs.Has(clusterID) {
		return fmt.Errorf("clusterID %d is already used", clusterID)
	}
	m.usedIDs.Insert(clusterID)
	return nil
}

func (m *clusterIDsManager) ReleaseClusterID(clusterID uint32) {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	m.usedIDs.Delete(clusterID)
}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Assign a unique cluster ID per remote cluster; fix the duplicate --cluster-id on the offending cluster.
  2. Ensure ReleaseClusterID is called when a remote cluster is disconnected/removed so IDs are freed.
  3. If a stale reservation persists after a crash, restart the component to reset the manager, then reconnect with correct IDs.

Example fix

// before
m.ReserveClusterID(2) // cluster B
m.ReserveClusterID(2) // cluster C — error
// after
m.ReserveClusterID(2) // cluster B
m.ReserveClusterID(3) // cluster C — unique ID
Defensive patterns

Strategy: try-catch

Validate before calling

if inUse, _ := mgr.reserved(id); inUse {
	return fmt.Errorf("cluster ID %d already reserved by another remote cluster", id)
}
if err := mgr.ReserveClusterID(id); err != nil { return err }

Try / catch

if err := mgr.ReserveClusterID(id); err != nil {
	if strings.Contains(err.Error(), "already used") {
		log.Errorf("cluster ID %d taken; call ReleaseClusterID on removal or assign a new ID", id)
	}
}

Prevention

When it happens

Trigger: Calling ReserveClusterID(id) twice for different clusters without ReleaseClusterID(id) between them, or connecting two remote clusters both configured with the same cluster-id.

Common situations: Two remote clusters misconfigured with the same --cluster-id; leaking reservations after a failed/disconnected remote cluster (missing ReleaseClusterID) so the ID stays 'used'; rapid reconnect loops reusing an ID.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/3290a7004fa4cea7. Report an issue: GitHub.