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
- Assign a unique cluster ID per remote cluster; fix the duplicate --cluster-id on the offending cluster.
- Ensure ReleaseClusterID is called when a remote cluster is disconnected/removed so IDs are freed.
- 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
- Always pair ReserveClusterID with ReleaseClusterID when a remote cluster disconnects.
- Enforce unique cluster IDs via a fleet-level allocation policy or controller.
- On startup, reconcile reserved IDs against the actual set of connected remote clusters.
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
- clusterID %d is assigned to the local cluster
- clusterID %d is reserved
- %w: %w
- ErrClusterIDChanged
- AddrCluster.UnmarshalJSON: bad address
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/3290a7004fa4cea7.
Report an issue: GitHub.