{"record":{"id":"28c957168b5af8db","repo":"plandex-ai/plandex","slug":"user-not-found-28c957","errorCode":null,"errorMessage":"User not found","messagePattern":"User not found","errorType":"http","errorClass":"http","httpStatus":404,"severity":"warning","filePath":"app/server/handlers/sessions.go","lineNumber":62,"sourceCode":"\t\t\thttp.Error(w, \"Error getting user: \"+err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\thasAccount = user != nil\n\t} else {\n\t\thasAccount = true\n\n\t\tuser, err := db.GetUser(req.UserId)\n\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Error getting user: %v\\n\", err)\n\t\t\thttp.Error(w, \"Error getting user: \"+err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tif user == nil {\n\t\t\tlog.Printf(\"User not found for id: %v\\n\", req.UserId)\n\t\t\thttp.Error(w, \"User not found\", http.StatusNotFound)\n\t\t\treturn\n\t\t}\n\n\t\tif user.Email != req.Email {\n\t\t\tlog.Printf(\"User email does not match for id: %v\\n\", req.UserId)\n\t\t\thttp.Error(w, \"User email does not match\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t}\n\n\tif req.RequireUser && !hasAccount {\n\t\tlog.Printf(\"User not found for email: %v\\n\", req.Email)\n\t\thttp.Error(w, \"User not found\", http.StatusNotFound)\n\t\treturn\n\t} else if req.RequireNoUser && hasAccount {\n\t\tlog.Printf(\"User already exists for email: %v\\n\", req.Email)\n\t\thttp.Error(w, \"User already exists\", http.StatusConflict)\n\t\treturn","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/sessions.go#L44-L80","documentation":"CreateEmailVerificationHandler returns HTTP 404 'User not found' when the request supplies a UserId but db.GetUser finds no user row for that ID. The endpoint treats a non-empty UserId as proof the caller already has an account, so an unknown ID is a hard stop before any verification pin is generated. This prevents issuing verification pins against nonexistent accounts.","triggerScenarios":"POSTing a body with a non-empty userId (CreateEmailVerificationRequest.UserId) for an account that was deleted, never created, or whose ID is stale/typo'd; also reusing an ID from a different database or after a DB reset.","commonSituations":"Client cached an old userId after a database wipe or staging reset; signed-up user's account was deleted by an admin; copying a userId from another environment (prod vs staging) or hardcoding a placeholder ID; case/whitespace differences are not the issue here since the ID is exact-match.","solutions":["Verify the userId exists in the users table (SELECT * FROM users WHERE id = ?) and correct any stale value on the client.","Clear the cached/stored userId on the client so the request is sent with an empty UserId, which routes lookup through email instead (db.GetUserByEmail).","If the account should exist, re-run the signup/registration flow to recreate the user, then retry verification.","Confirm the server is pointed at the intended database (DATABASE_URL/connection config) - the user may exist in another environment.","Check for ID truncation or formatting mistakes (whitespace, truncated string) in the client payload before sending."],"exampleFix":"// before\nreq := shared.CreateEmailVerificationRequest{ UserId: staleUserID, Email: email }\n// after\n// only send UserId if the local session still has a valid account;\n// otherwise fall back to email-only lookup\nreq := shared.CreateEmailVerificationRequest{ Email: email }\nif accountStillExists(staleUserID) {\n    req.UserId = staleUserID\n}","handlingStrategy":"validation","validationCode":"// before calling the API, confirm the stored userId is non-empty\nif strings.TrimSpace(userSession.UserId) == \"\" {\n    // no stored account: send email-only request instead of a stale UserId\n    req.UserId = \"\"\n}","typeGuard":"func hasUserId(req shared.CreateEmailVerificationRequest) bool {\n    return strings.TrimSpace(req.UserId) != \"\"\n}","tryCatchPattern":"// Go HTTP: check status before decoding\nresp, err := http.Post(url, \"application/json\", body)\nif err != nil { return err }\nif resp.StatusCode == http.StatusNotFound {\n    // treat as 'stale account': clear local session and fall back to email-only flow\n    clearStoredUser()\n    return retryWithEmailOnly()\n}","preventionTips":["Never persist userId across database resets; re-validate it on app start via a session-check endpoint.","Send an empty UserId unless the client holds an active, confirmed session.","Include environment (staging/prod) in your config to avoid cross-environment ID reuse.","Handle 404 from this endpoint by falling back to email-based lookup instead of failing hard."],"tags":["http-404","not-found","email-verification","auth","user-lookup"],"backgroundTag":"user-not-found","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}