{"record":{"id":"d1fbe95bff2d9c13","repo":"XTLS/Xray-core","slug":"onlinemap-s-already-registered","errorCode":null,"errorMessage":"OnlineMap %s already registered.","messagePattern":"OnlineMap (.+?) already registered\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/stats/stats.go","lineNumber":106,"sourceCode":"// VisitCounters calls visitor function on all managed counters.\nfunc (m *Manager) VisitCounters(visitor func(string, stats.Counter) bool) {\n\tm.access.RLock()\n\tdefer m.access.RUnlock()\n\n\tfor name, c := range m.counters {\n\t\tif !visitor(name, c) {\n\t\t\tbreak\n\t\t}\n\t}\n}\n\n// RegisterOnlineMap implements stats.Manager.\nfunc (m *Manager) RegisterOnlineMap(name string) (stats.OnlineMap, error) {\n\tm.access.Lock()\n\tdefer m.access.Unlock()\n\n\tif _, found := m.onlineMaps[name]; found {\n\t\treturn nil, errors.New(\"OnlineMap \", name, \" already registered.\")\n\t}\n\terrors.LogDebug(context.Background(), \"create new OnlineMap \", name)\n\tom := NewOnlineMap()\n\tm.onlineMaps[name] = om\n\treturn om, nil\n}\n\n// GetOrRegisterOnlineMap implements stats.Manager.\nfunc (m *Manager) GetOrRegisterOnlineMap(name string) (stats.OnlineMap, error) {\n\tm.access.Lock()\n\tdefer m.access.Unlock()\n\n\tif om, found := m.onlineMaps[name]; found {\n\t\treturn om, nil\n\t}\n\terrors.LogDebug(context.Background(), \"create new OnlineMap \", name)\n\tom := NewOnlineMap()\n\tm.onlineMaps[name] = om","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/XTLS/Xray-core/blob/7d214f8b094f75322fa3990f8aadad1c912f24f5/app/stats/stats.go#L88-L124","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use GetOrRegisterOnlineMap(name) which returns the existing map instead of erroring.","Ensure teardown paths (RemoveHandler / user removal) also remove the OnlineMap so re-adding a user can register fresh.","Audit callers of RegisterOnlineMap to confirm only one component owns a given name."],"exampleFix":"// before\nom, err := statsManager.RegisterOnlineMap(\"user>>>a@b.com\")\n\n// after\nom, err := statsManager.GetOrRegisterOnlineMap(\"user>>>a@b.com\")","handlingStrategy":"fallback","validationCode":"if _, found := m.GetOnlineMap(name); found { /* exists: reuse instead of register */ }","typeGuard":null,"tryCatchPattern":"om, err := m.RegisterOnlineMap(name)\nif err != nil {\n    if existing, ok2 := m.GetOnlineMap(name); ok2 { om = existing } else { return err }\n}","preventionTips":["Use GetOrRegisterOnlineMap in dynamic user-management paths","Tear down OnlineMap registrations when users are removed"],"tags":["stats","duplicate-registration","online-map","xray"],"backgroundTag":null,"analyzedSha":"7d214f8b094f75322fa3990f8aadad1c912f24f5","analyzedAt":"2026-08-15T14:26:24.325Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}