{"record":{"id":"ef67e4a2f22a44cb","repo":"plandex-ai/plandex","slug":"org-not-found","errorCode":null,"errorMessage":"org not found","messagePattern":"org not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"app/server/db/org_helpers.go","lineNumber":76,"sourceCode":"\t\tvar orgsFromInvites []*Org\n\t\tquery := fmt.Sprintf(\"SELECT %s FROM orgs WHERE id = ANY($1)\", orgFields)\n\t\terr = Conn.Select(&orgsFromInvites, query, pq.Array(orgIds))\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error getting orgs from invites: %v\", err)\n\t\t}\n\t\torgs = append(orgs, orgsFromInvites...)\n\t}\n\n\treturn orgs, nil\n}\nfunc GetOrg(orgId string) (*Org, error) {\n\tvar org Org\n\tquery := fmt.Sprintf(\"SELECT %s FROM orgs WHERE id = $1\", orgFields)\n\terr := Conn.Get(&org, query, orgId)\n\n\tif err != nil {\n\t\tif err == sql.ErrNoRows {\n\t\t\treturn nil, fmt.Errorf(\"org not found\")\n\t\t}\n\n\t\treturn nil, fmt.Errorf(\"error getting org: %v\", err)\n\t}\n\n\treturn &org, nil\n}\n\nfunc ValidateOrgMembership(userId string, orgId string) (bool, error) {\n\tvar count int\n\terr := Conn.QueryRow(\"SELECT COUNT(*) FROM orgs_users WHERE user_id = $1 AND org_id = $2\", userId, orgId).Scan(&count)\n\n\tif err != nil {\n\t\treturn false, fmt.Errorf(\"error validating org membership: %v\", err)\n\t}\n\n\treturn count > 0, nil\n}","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/org_helpers.go#L58-L94","documentation":"GetOrg maps sql.ErrNoRows from the single-row SELECT on orgs to the exact message 'org not found'. This is the deliberate no-result signal: the orgId simply has no row in orgs. Any other query error takes the separate 'error getting org' path.","triggerScenarios":"Caller passes an orgId that doesn't exist (typo, wrong environment, deleted org) to GetOrg via handlers like InviteUserHandler or getApiOrg; org row deleted while a user held a stale reference (e.g. from an invite).","commonSituations":"Client cached an orgId from another environment (staging vs prod); org deleted between listing and detail fetch; user manually editing an org id in an API call; invite pointing at a purged org.","solutions":["Verify the orgId exists: SELECT id FROM orgs WHERE id = '<id>' in the target environment","Return 404 to the client and have it refresh its org list","Clean up dangling references (invites, memberships) when orgs are deleted","Check environment/config — the id may belong to staging while querying prod"],"exampleFix":"// before\norg, err := db.GetOrg(orgId)\nif err != nil { return err }\n// after\norg, err := db.GetOrg(orgId)\nif err != nil {\n    if err.Error() == \"org not found\" { http.Error(w, \"org not found\", http.StatusNotFound); return }\n    return err\n}","handlingStrategy":"try-catch","validationCode":"var exists bool\nerr := Conn.Get(&exists, \"SELECT EXISTS(SELECT 1 FROM orgs WHERE id = $1)\", orgId)\nif err == nil && !exists { http.Error(w, \"org not found\", http.StatusNotFound); return }","typeGuard":"func isOrgNotFound(err error) bool { return err != nil && err.Error() == \"org not found\" }","tryCatchPattern":"org, err := db.GetOrg(orgId)\nif err != nil {\n    if isOrgNotFound(err) { http.Error(w, \"org not found\", http.StatusNotFound); return }\n    http.Error(w, \"internal error\", http.StatusInternalServerError)\n    return\n}","preventionTips":["Map this sentinel to HTTP 404 in every handler that calls GetOrg","Validate orgId format (UUID) before lookup","Refresh cached org ids client-side; purge invites/memberships when an org is deleted","Check you are querying the right environment's database","Compare with errors.Is/As rather than string matching long-term — prefer a typed sentinel error"],"tags":["database","postgres","not-found","http-404"],"backgroundTag":"record-not-found","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}