{"record":{"id":"f184d1467ebd82c9","repo":"m1k1o/neko","slug":"session-token-already-exists","errorCode":null,"errorMessage":"session token already exists","messagePattern":"session token already exists","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/session/manager.go","lineNumber":106,"sourceCode":"\ttotalUsers      atomic.Int32\n\tlastUserLeftAt  atomic.Value\n}\n\nfunc (manager *SessionManagerCtx) Create(id string, profile types.MemberProfile) (types.Session, string, error) {\n\ttoken, err := utils.NewUID(64)\n\tif err != nil {\n\t\treturn nil, \"\", err\n\t}\n\n\tmanager.sessionsMu.Lock()\n\tif _, ok := manager.sessions[id]; ok {\n\t\tmanager.sessionsMu.Unlock()\n\t\treturn nil, \"\", types.ErrSessionAlreadyExists\n\t}\n\n\tif _, ok := manager.tokens[token]; ok {\n\t\tmanager.sessionsMu.Unlock()\n\t\treturn nil, \"\", errors.New(\"session token already exists\")\n\t}\n\n\tsession := &SessionCtx{\n\t\tid:      id,\n\t\ttoken:   token,\n\t\tmanager: manager,\n\t\tlogger:  manager.logger.With().Str(\"session_id\", id).Logger(),\n\t\tprofile: profile,\n\t}\n\n\tmanager.tokens[token] = id\n\tmanager.sessions[id] = session\n\tmanager.sessionsMu.Unlock()\n\n\tmanager.emmiter.Emit(\"created\", session)\n\tmanager.save()\n\n\treturn session, token, nil","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/m1k1o/neko/blob/b0f01cedea68893e85a3fd852c0521238c285695/server/internal/session/manager.go#L88-L124","documentation":"Create in server/internal/session/manager.go throws this ad-hoc error when the generated (or supplied) session token is already present in manager.tokens. Sessions and their login tokens are stored in two maps; while the session ID may be free, the token must also be unique. The manager returns (nil, \"\") and closes over this condition to prevent two sessions sharing one token, which would let one token authenticate to multiple sessions.","triggerScenarios":"Calling sessionMgr.Create with a token string that an existing live session already holds (e.g. manually supplying a fixed/derived token in Create's arguments instead of letting the manager generate a random one, or after restoring/duplicating sessions without clearing the tokens map).","commonSituations":"Developers wiring custom token generation (e.g. deriving tokens from a user ID or a static config value) instead of the default random token; tests that create two sessions with the same hardcoded token; restart/reconnect logic that reuses a previously issued token while the old session still exists in the manager.","solutions":["Let the manager generate a random token instead of passing a fixed one to Create.","Ensure the old session is destroyed (Destroy/logout) before reusing its token.","If migrating state, rebuild the tokens map consistently with the sessions map so no stale token entries remain.","Handle the returned error by retrying Create with a freshly generated token."],"exampleFix":"// before\nsession, token, err := manager.Create(\"user-42\", \"static-token\", profile)\n// after\ntoken, err := randomToken() // e.g. crypto/rand generated\nif err != nil { return err }\nsession, token, err := manager.Create(\"user-42\", token, profile)","handlingStrategy":"retry","validationCode":"manager.sessionsMu.Lock()\n_, idTaken := manager.sessions[id]\n_, tokTaken := manager.tokens[token]\nmanager.sessionsMu.Unlock()\nif tokTaken {\n  token = generateNewRandomToken() // regenerate before calling Create\n}","typeGuard":null,"tryCatchPattern":"session, tok, err := manager.Create(id, token, profile)\nif err != nil && err.Error() == \"session token already exists\" {\n  return manager.Create(id, generateNewRandomToken(), profile) // retry once with fresh token\n}","preventionTips":["Always let the manager generate tokens with crypto/rand instead of supplying fixed tokens.","Destroy old sessions before reusing their tokens.","Never derive tokens from user IDs or predictable values.","In tests, use unique tokens per session creation."],"tags":["session","token-collision","go"],"backgroundTag":"session-token-already-exists","analyzedSha":"b0f01cedea68893e85a3fd852c0521238c285695","analyzedAt":"2026-09-01T10:35:56.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}