{"record":{"id":"8017f138d3e1a138","repo":"plandex-ai/plandex","slug":"error-getting-member-role-id-v","errorCode":null,"errorMessage":"error getting member role id: %v","messagePattern":"error getting member role id: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/rbac_helpers.go","lineNumber":93,"sourceCode":"func cacheOrgOwnerRoleId() error {\n\tvar roleId string\n\terr := Conn.Get(&roleId, \"SELECT id FROM org_roles WHERE name = 'owner'\")\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting owner role id: %v\", err)\n\t}\n\n\torgOwnerRoleId = roleId\n\n\treturn nil\n}\n\nfunc cacheOrgMemberRoleId() error {\n\tvar roleId string\n\terr := Conn.Get(&roleId, \"SELECT id FROM org_roles WHERE name = 'member'\")\n\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting member role id: %v\", err)\n\t}\n\n\torgMemberRoleId = roleId\n\n\treturn nil\n}\n","sourceCodeStart":75,"sourceCodeEnd":100,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/rbac_helpers.go#L75-L100","documentation":"cacheOrgMemberRoleId runs 'SELECT id FROM org_roles WHERE name = member' via Conn.Get; any failure (no matching row, dead connection, query error) is wrapped with this message and surfaces through GetOrgMemberRoleId and CacheOrgRoleIds. It is the low-level lookup for the member role id.","triggerScenarios":"First GetOrgMemberRoleId (via AddOrgDomainUsers) or CacheOrgRoleIds call when org_roles lacks a 'member' row, the table doesn't exist, or the DB is unreachable.","commonSituations":"Unseeded or partially seeded database; connection refused after DB restart; migrations not applied on a fresh environment.","solutions":["Insert the 'member' row: INSERT INTO org_roles (name) VALUES ('member');","Run pending migrations and seed both roles together","Distinguish sql.ErrNoRows (data missing) from ping/connection errors in the wrapped error","Ensure DB initialization ran before the first call"],"exampleFix":"// before\nvar roleId string\nerr := Conn.Get(&roleId, \"SELECT id FROM org_roles WHERE name = 'member'\")\n// after\nvar roleId string\nerr := Conn.Get(&roleId, \"SELECT id FROM org_roles WHERE name = 'member'\")\nif errors.Is(err, sql.ErrNoRows) {\n\treturn fmt.Errorf(\"org_roles 'member' row missing — run seed migrations\")\n}","handlingStrategy":"retry","validationCode":"var n int\nerr := db.QueryRow(\"SELECT count(*) FROM org_roles WHERE name = 'member'\").Scan(&n)\nif err != nil || n == 0 {\n\treturn fmt.Errorf(\"member role row missing\")\n}","typeGuard":"func isNoRows(err error) bool {\n\treturn err != nil && (errors.Is(err, sql.ErrNoRows) || strings.Contains(err.Error(), \"sql: no rows\"))\n}","tryCatchPattern":"roleId, err := GetOrgMemberRoleId()\nif err != nil {\n\tif isNoRows(err) {\n\t\treturn fmt.Errorf(\"seed data missing: %w\", err)\n\t}\n\treturn retryWithBackoff(3, func() error { // transient connectivity\n\t\t_, e := GetOrgMemberRoleId()\n\t\treturn e\n\t})\n}","preventionTips":["Distinguish sql.ErrNoRows from connection errors before deciding to retry","Seed both roles atomically","Warm caches at startup so failures surface early"],"tags":["database","sql","rbac","no-rows"],"backgroundTag":"sql-no-rows","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"}