XTLS/Xray-core · error

OnlineMap %s already registered.

Error message

OnlineMap %s already registered.

What it means

Returned by stats.Manager.RegisterOnlineMap when an OnlineMap with the same name is already registered. OnlineMap tracks per-entity online status (typically per user IP/session state); names are unique per manager. The idempotent counterpart is GetOrRegisterOnlineMap.

Source

Thrown at app/stats/stats.go:106

// VisitCounters calls visitor function on all managed counters.
func (m *Manager) VisitCounters(visitor func(string, stats.Counter) bool) {
	m.access.RLock()
	defer m.access.RUnlock()

	for name, c := range m.counters {
		if !visitor(name, c) {
			break
		}
	}
}

// RegisterOnlineMap implements stats.Manager.
func (m *Manager) RegisterOnlineMap(name string) (stats.OnlineMap, error) {
	m.access.Lock()
	defer m.access.Unlock()

	if _, found := m.onlineMaps[name]; found {
		return nil, errors.New("OnlineMap ", name, " already registered.")
	}
	errors.LogDebug(context.Background(), "create new OnlineMap ", name)
	om := NewOnlineMap()
	m.onlineMaps[name] = om
	return om, nil
}

// GetOrRegisterOnlineMap implements stats.Manager.
func (m *Manager) GetOrRegisterOnlineMap(name string) (stats.OnlineMap, error) {
	m.access.Lock()
	defer m.access.Unlock()

	if om, found := m.onlineMaps[name]; found {
		return om, nil
	}
	errors.LogDebug(context.Background(), "create new OnlineMap ", name)
	om := NewOnlineMap()
	m.onlineMaps[name] = om

View on GitHub (pinned to 7d214f8b09)

Solutions

  1. Use GetOrRegisterOnlineMap(name) which returns the existing map instead of erroring.
  2. Ensure teardown paths (RemoveHandler / user removal) also remove the OnlineMap so re-adding a user can register fresh.
  3. Audit callers of RegisterOnlineMap to confirm only one component owns a given name.

Example fix

// before
om, err := statsManager.RegisterOnlineMap("user>>>a@b.com")

// after
om, err := statsManager.GetOrRegisterOnlineMap("user>>>a@b.com")
Defensive patterns

Strategy: fallback

Validate before calling

if _, found := m.GetOnlineMap(name); found { /* exists: reuse instead of register */ }

Try / catch

om, err := m.RegisterOnlineMap(name)
if err != nil {
    if existing, ok2 := m.GetOnlineMap(name); ok2 { om = existing } else { return err }
}

Prevention

When it happens

Trigger: Calling RegisterOnlineMap(name) twice on the same Manager — e.g. an handler service being restarted (add/remove user via handler service API) while its online map registration persists under the same user name.

Common situations: Dynamic user management through the HandlerService API where a removed user's OnlineMap was not cleaned up before re-adding; multiple extensions mistakenly registering online maps under a fixed shared name.

Related errors


AI-assisted analysis of XTLS/Xray-core@7d214f8b09 (2026-08-15). Data as JSON: /api/errors/d1fbe95bff2d9c13. Report an issue: GitHub.