{"record":{"id":"db539c2c5fbc5a32","repo":"plandex-ai/plandex","slug":"error-getting-user-db539c","errorCode":null,"errorMessage":"Error getting user: ","messagePattern":"Error getting user: ","errorType":"http","errorClass":"http","httpStatus":500,"severity":"error","filePath":"app/server/handlers/sessions.go","lineNumber":44,"sourceCode":"\t\treturn\n\t}\n\n\tvar req shared.CreateEmailVerificationRequest\n\terr = json.Unmarshal(body, &req)\n\tif err != nil {\n\t\tlog.Printf(\"Error unmarshalling request: %v\\n\", err)\n\t\thttp.Error(w, \"Error unmarshalling request: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\treq.Email = strings.ToLower(req.Email)\n\n\tvar hasAccount bool\n\tif req.UserId == \"\" {\n\t\tuser, err := db.GetUserByEmail(req.Email)\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\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)","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/sessions.go#L26-L62","documentation":"When the request has no UserId, the handler looks up the account by email via db.GetUserByEmail(req.Email). Any error returned from that database call is answered with 500 \"Error getting user: <err>\". Note this is distinct from \"user not found\": GetUserByEmail returning (nil, nil) is handled as hasAccount=false, so a 500 means the lookup itself failed.","triggerScenarios":"Postgres is down, unreachable, or the connection pool is exhausted; the users table is missing/migrated out of sync; a database timeout or context cancellation during the query; transient network failure between the server and the database.","commonSituations":"DB container stopped during local development; DATABASE_URL misconfigured after an env change; schema migrations not applied so the query references a missing column/table; connection limit hit under load during email-verification signup flows.","solutions":["Check the server log for the wrapped database error text to identify connection vs schema failure.","Verify the database is running and reachable (DATABASE_URL / POSTGRES_HOST env, docker ps for the postgres container).","Apply pending schema migrations so the users table matches what GetUserByEmail queries.","Retry the signup/verification request — transient connection-pool exhaustion resolves on retry.","If persistent, restart the server to rebuild DB connections and inspect connection-pool settings."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// client-side: only send a syntactically valid, lowercased email so the DB lookup has a chance\nemail = strings.ToLower(strings.TrimSpace(email))\nif email == \"\" || !strings.Contains(email, \"@\") {\n    return errors.New(\"invalid email; fix before calling create-email-verification\")\n}","typeGuard":null,"tryCatchPattern":"// Go client: retry on 500 with DB-flavored error text, back off between attempts\nresp, err := client.Do(req)\nif err != nil || resp.StatusCode == http.StatusInternalServerError {\n    body, _ := io.ReadAll(resp.Body)\n    if strings.Contains(string(body), \"Error getting user\") {\n        return retryWithBackoff(req) // transient DB failure\n    }\n    return fmt.Errorf(\"user lookup failed permanently: %s\", body)\n}","preventionTips":["Treat \"Error getting user: \" 500s as database-health signals; alert on DB connectivity first.","Keep schema migrations applied so users-table queries never hit missing columns.","Send lowercased emails (the handler lowercases anyway) to keep lookups deterministic.","Retry transient DB failures with backoff rather than surfacing 500s to end users.","Monitor Postgres connection-pool saturation during signup/verification bursts."],"tags":["go","database","postgres","user-lookup"],"backgroundTag":"database-query-failed","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"}