{"record":{"id":"35b32494fe9c5aa0","repo":"m1k1o/neko","slug":"session-not-found-35b324","errorCode":null,"errorMessage":"session not found","messagePattern":"session not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"server/internal/http/legacy/handler.go","lineNumber":433,"sourceCode":"\t\t\treturn utils.HttpInternalServerError().WithInternalErr(err)\n\t\t}\n\n\t\t// copy the body to the response writer\n\t\t_, err = io.Copy(w, body)\n\t\treturn err\n\t})\n\n\tr.Get(\"/health\", func(w http.ResponseWriter, r *http.Request) error {\n\t\t_, err := w.Write([]byte(\"true\"))\n\t\treturn err\n\t})\n}\n\nfunc (h *LegacyHandler) ban(sessionId string) error {\n\t// find session by id\n\tip, ok := h.sessionIPs[sessionId]\n\tif !ok {\n\t\treturn fmt.Errorf(\"session not found\")\n\t}\n\n\th.bannedIPs[ip] = struct{}{}\n\treturn nil\n}\n\nfunc (h *LegacyHandler) isBanned(r *http.Request) bool {\n\tip := getIp(r)\n\t_, ok := h.bannedIPs[ip]\n\treturn ok\n}\n\nfunc getIp(r *http.Request) string {\n\tip, _, err := net.SplitHostPort(r.RemoteAddr)\n\tif err != nil {\n\t\tif e, ok := err.(*net.AddrError); ok && e.Err == \"missing port in address\" {\n\t\t\treturn r.RemoteAddr\n\t\t}","sourceCodeStart":415,"sourceCodeEnd":451,"githubUrl":"https://github.com/m1k1o/neko/blob/b0f01cedea68893e85a3fd852c0521238c285695/server/internal/http/legacy/handler.go#L415-L451","documentation":"This error is returned by LegacyHandler.ban when a ban request references a sessionId that is not present in the handler's in-memory sessionIPs map. The legacy handler only records session-to-IP mappings when a session registers locally, so banning an unknown, already-disconnected, or never-seen session id yields this error. It is a client-side lookup failure within the proxy, not a backend failure.","triggerScenarios":"Calling LegacyHandler.ban(sessionId) with an id never registered in h.sessionIPs — e.g. wsToBackend receives a moderation/ban event (wstobackend.go:339) for a session that was created on a different node, already destroyed, or whose mapping was lost on restart.","commonSituations":"Multi-instance deployments where the ban event arrives at a node that does not own the session; banning a user right after they disconnect; stale session ids cached in admin UIs; server restart wiping the in-memory map while clients still reference old ids.","solutions":["Verify the sessionId exists before banning by checking the sessions list (GET /api/sessions via apiReq).","Deploy sticky routing or a shared session registry so the ban reaches the node owning the session.","Handle the error gracefully in wsToBackend: log and skip instead of failing the moderation flow.","If restarts lose mappings, persist sessionIPs or re-derive IP from the backend API instead of local memory."],"exampleFix":"// before\nip, ok := h.sessionIPs[sessionId]\nif !ok {\n    return fmt.Errorf(\"session not found\")\n}\n// after\nip, ok := h.sessionIPs[sessionId]\nif !ok {\n    log.Warn().Str(\"sessionId\", sessionId).Msg(\"ban skipped: session not found on this node\")\n    return nil // or a typed ErrSessionNotFound\n}","handlingStrategy":"validation","validationCode":"if _, ok := handler.sessionIPs[sessionId]; !ok {\n    return fmt.Errorf(\"cannot ban %q: session not registered on this node\", sessionId)\n}","typeGuard":"func sessionKnown(h *LegacyHandler, sessionId string) bool {\n    _, ok := h.sessionIPs[sessionId]\n    return ok\n}","tryCatchPattern":"if err := h.ban(id); err != nil {\n    if err.Error() == \"session not found\" {\n        log.Warn().Str(\"sessionId\", id).Msg(\"ban skipped: session not on this node\")\n        return nil\n    }\n    return err\n}","preventionTips":["Check session existence via /api/sessions before issuing a ban.","Design ban handling to be idempotent across nodes (shared session store).","Treat 'session not found' as a no-op in moderation flows, not a failure.","Re-derive the client IP from the backend API when the local map misses."],"tags":["session","lookup","in-memory-state"],"backgroundTag":"session-not-found","analyzedSha":"b0f01cedea68893e85a3fd852c0521238c285695","analyzedAt":"2026-09-01T10:35:56.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}