plandex-ai/plandex · warning · http
User not found
Error message
User not found
What it means
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.
Source
Thrown at app/server/handlers/sessions.go:62
http.Error(w, "Error getting user: "+err.Error(), http.StatusInternalServerError)
return
}
hasAccount = user != nil
} else {
hasAccount = true
user, err := db.GetUser(req.UserId)
if err != nil {
log.Printf("Error getting user: %v\n", err)
http.Error(w, "Error getting user: "+err.Error(), http.StatusInternalServerError)
return
}
if user == nil {
log.Printf("User not found for id: %v\n", req.UserId)
http.Error(w, "User not found", http.StatusNotFound)
return
}
if user.Email != req.Email {
log.Printf("User email does not match for id: %v\n", req.UserId)
http.Error(w, "User email does not match", http.StatusBadRequest)
return
}
}
if req.RequireUser && !hasAccount {
log.Printf("User not found for email: %v\n", req.Email)
http.Error(w, "User not found", http.StatusNotFound)
return
} else if req.RequireNoUser && hasAccount {
log.Printf("User already exists for email: %v\n", req.Email)
http.Error(w, "User already exists", http.StatusConflict)
returnView on GitHub (pinned to e2d772072e)
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.
Example fix
// before
req := shared.CreateEmailVerificationRequest{ UserId: staleUserID, Email: email }
// after
// only send UserId if the local session still has a valid account;
// otherwise fall back to email-only lookup
req := shared.CreateEmailVerificationRequest{ Email: email }
if accountStillExists(staleUserID) {
req.UserId = staleUserID
} Defensive patterns
Strategy: validation
Validate before calling
// before calling the API, confirm the stored userId is non-empty
if strings.TrimSpace(userSession.UserId) == "" {
// no stored account: send email-only request instead of a stale UserId
req.UserId = ""
} Type guard
func hasUserId(req shared.CreateEmailVerificationRequest) bool {
return strings.TrimSpace(req.UserId) != ""
} Try / catch
// Go HTTP: check status before decoding
resp, err := http.Post(url, "application/json", body)
if err != nil { return err }
if resp.StatusCode == http.StatusNotFound {
// treat as 'stale account': clear local session and fall back to email-only flow
clearStoredUser()
return retryWithEmailOnly()
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "User not found", "Invalid user", and "does not exist": what missing-user lookup errors mean across Rocket.Chat, LiteLLM, Phabricator, rustfs, and pnpm — this error's family across 10 libraries.
Related errors
- error verifying email: %v
- error creating email verification: %v
- error verifying email: %v
- org not found
- error validating email verification: %v
AI-assisted analysis of plandex-ai/plandex@e2d772072e (2026-09-05).
Data as JSON: /api/errors/28c957168b5af8db.
Report an issue: GitHub.