{"record":{"id":"74dbae3e40340546","repo":"plandex-ai/plandex","slug":"org-owner-role-id-is-empty","errorCode":null,"errorMessage":"org owner role id is empty","messagePattern":"org owner role id is empty","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/rbac_helpers.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"fmt\"\n\t\"log\"\n)\n\nvar orgOwnerRoleId string\nvar orgMemberRoleId string\n\nfunc GetOrgOwnerRoleId() (string, error) {\n\tif orgOwnerRoleId == \"\" {\n\t\terr := cacheOrgOwnerRoleId()\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"error getting org owner role id: %v\", err)\n\t\t}\n\t}\n\n\tif orgOwnerRoleId == \"\" {\n\t\treturn \"\", fmt.Errorf(\"org owner role id is empty\")\n\t}\n\n\treturn orgOwnerRoleId, nil\n}\n\nfunc GetOrgMemberRoleId() (string, error) {\n\tif orgMemberRoleId == \"\" {\n\t\terr := cacheOrgMemberRoleId()\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"error getting org member role id: %v\", err)\n\t\t}\n\t}\n\n\tif orgMemberRoleId == \"\" {\n\t\treturn \"\", fmt.Errorf(\"org member role id is empty\")\n\t}\n\n\treturn orgMemberRoleId, nil","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/rbac_helpers.go#L2-L38","documentation":"This is the fallback guard in GetOrgOwnerRoleId: even after cacheOrgOwnerRoleId returned nil, the package-level orgOwnerRoleId is still empty, so the function refuses to return an invalid role id. It indicates an inconsistent cache state rather than a failed query.","triggerScenarios":"cacheOrgOwnerRoleId succeeded but wrote nothing usable, or orgOwnerRoleId was reset/cleared concurrently after being cached; effectively only reachable if the caching logic or global variable is corrupted.","commonSituations":"Code changes that clear the package global; race between multiple goroutines initializing the cache; a schema where the 'owner' row id is legitimately an empty string.","solutions":["Call CacheOrgRoleIds() at startup (MustInitDb) and fail fast if it errors","Add a mutex or use sync.Once around cacheOrgOwnerRoleId to prevent concurrent reset","Log and re-call cacheOrgOwnerRoleId once inside this branch before giving up","Verify no code path assigns orgOwnerRoleId = \"\" after startup"],"exampleFix":"// before\nif orgOwnerRoleId == \"\" {\n\treturn \"\", fmt.Errorf(\"org owner role id is empty\")\n}\n// after\nif orgOwnerRoleId == \"\" {\n\tif err := cacheOrgOwnerRoleId(); err != nil {\n\t\treturn \"\", fmt.Errorf(\"org owner role id is empty: %v\", err)\n\t}\n}","handlingStrategy":"validation","validationCode":"if orgOwnerRoleId == \"\" {\n\tif err := CacheOrgRoleIds(); err != nil {\n\t\treturn fmt.Errorf(\"cannot resolve owner role id: %w\", err)\n\t}\n}\nrole, err := GetOrgOwnerRoleId()","typeGuard":"func roleCacheReady() bool {\n\treturn orgOwnerRoleId != \"\" && orgMemberRoleId != \"\"\n}","tryCatchPattern":null,"preventionTips":["Initialize the cache once with sync.Once and treat empty cache as fatal","Never assign the package globals outside the cache functions","Re-derive the value instead of returning bare 'is empty' errors"],"tags":["database","rbac","cache","state"],"backgroundTag":"empty-role-id-cache","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"}