{"record":{"id":"2fa3633bb9742dfe","repo":"plandex-ai/plandex","slug":"error-getting-user-2fa363","errorCode":null,"errorMessage":"Error getting user: ","messagePattern":"Error getting user: ","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"app/server/handlers/invites.go","lineNumber":93,"sourceCode":"\tsplit := strings.Split(req.Email, \"@\")\n\tif len(split) != 2 {\n\t\tlog.Printf(\"Invalid email: %v\\n\", req.Email)\n\t\thttp.Error(w, \"Invalid email: \"+req.Email, http.StatusBadRequest)\n\t\treturn\n\t}\n\tdomain := &split[1]\n\n\tif org.AutoAddDomainUsers && org.Domain == domain {\n\t\tlog.Printf(\"User already has access to org via domain: %v\\n\", domain)\n\t\thttp.Error(w, \"User already has access to org via domain: \"+*domain, http.StatusBadRequest)\n\t}\n\n\t// ensure user with this email isn't already in the org\n\tuser, err := db.GetUserByEmail(req.Email)\n\n\tif err != nil {\n\t\tlog.Printf(\"Error getting user: %v\\n\", err)\n\t\thttp.Error(w, \"Error getting user: \"+err.Error(), http.StatusInternalServerError)\n\t\treturn\n\t}\n\n\tif user != nil {\n\t\tisMember, err := db.ValidateOrgMembership(user.Id, auth.OrgId)\n\n\t\tif err != nil {\n\t\t\tlog.Printf(\"Error validating org membership: %v\\n\", err)\n\t\t\thttp.Error(w, \"Error validating org membership: \"+err.Error(), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tif isMember {\n\t\t\tlog.Println(\"User is already a member of org\")\n\t\t\thttp.Error(w, \"User is already a member of org\", http.StatusBadRequest)\n\t\t\treturn\n\t\t}\n\t}","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/handlers/invites.go#L75-L111","documentation":"To prevent duplicate members, the handler looks up an existing user by email with db.GetUserByEmail(req.Email). If that query fails, the handler responds 500 with 'Error getting user: <err>'. Like the other 5xx paths, this reflects a database-layer failure rather than bad input (a 'not found' result returns nil user, not an error).","triggerScenarios":"db.GetUserByEmail fails due to Postgres unreachability, connection-pool exhaustion, query timeout, missing/out-of-date users table schema, or a serialization issue on the row.","commonSituations":"Database outage or failover during the invite; DATABASE_URL misconfig; migrations not applied after an upgrade; transient network errors between server and DB under load.","solutions":["Read the cause after 'Error getting user: ' in the response/log to identify the concrete DB error","Confirm Postgres health and DATABASE_URL reachability; check connection-pool limits under load","Run pending database migrations, then retry the invite","Simply retry on transient errors; escalate to DB inspection (logs, pg_stat_activity) if it persists"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight: verify DB-dependent endpoints are healthy before bulk invites\nif err := client.HealthCheck(ctx); err != nil {\n    return fmt.Errorf(\"server database unhealthy, deferring invites: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"err := client.InviteUser(ctx, email, roleID)\nif err != nil && strings.Contains(err.Error(), \"Error getting user\") {\n    // 500 from DB lookup — retry with backoff for transient failures\n    return retryWithBackoff(func() error { return client.InviteUser(ctx, email, roleID) })\n}","preventionTips":["Monitor Postgres availability and connection-pool usage","Run DB migrations on every server upgrade","Batch invites with retries and backoff rather than tight loops","Alert on recurring 'Error getting user' 500s — points at persistent DB issues"],"tags":["database","postgres","http","go"],"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"}