{"record":{"id":"f94572e071f5af65","repo":"plandex-ai/plandex","slug":"error-getting-all-invites-for-org-v","errorCode":null,"errorMessage":"error getting all invites for org: %v","messagePattern":"error getting all invites for org: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/server/db/invite_helpers.go","lineNumber":68,"sourceCode":"}\n\nfunc ListPendingInvites(orgId string) ([]*Invite, error) {\n\tvar invites []*Invite\n\terr := Conn.Select(&invites, \"SELECT * FROM invites WHERE org_id = $1 AND accepted_at IS NULL\", orgId)\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting pending invites for org: %v\", err)\n\t}\n\n\treturn invites, nil\n}\n\nfunc ListAllInvites(orgId string) ([]*Invite, error) {\n\tvar invites []*Invite\n\terr := Conn.Select(&invites, \"SELECT * FROM invites WHERE org_id = $1\", orgId)\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting all invites for org: %v\", err)\n\t}\n\n\treturn invites, nil\n}\n\nfunc ListAcceptedInvites(orgId string) ([]*Invite, error) {\n\tvar invites []*Invite\n\terr := Conn.Select(&invites, \"SELECT * FROM invites WHERE org_id = $1 AND accepted_at IS NOT NULL\", orgId)\n\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error getting accepted invites for org: %v\", err)\n\t}\n\n\treturn invites, nil\n}\n\nfunc GetPendingInvitesForEmail(email string) ([]*Invite, error) {\n\temail = strings.ToLower(email)","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/server/db/invite_helpers.go#L50-L86","documentation":"ListAllInvites selects every invite (accepted or pending) for an org. All non-nil errors from Conn.Select are wrapped with this message; an empty org simply yields a nil slice. It indicates the org-wide invite listing query failed at the database level.","triggerScenarios":"Conn.Select(\"SELECT * FROM invites WHERE org_id = $1\", orgId) fails: bad org_id format vs. uuid column, connection failure/timeout, or schema drift causing scan errors into the Invite struct. Called from ListAllInvitesHandler.","commonSituations":"Admin UI listing all invites right after a schema migration was added but the server binary (or Invite struct) is older, or transient DB outages during traffic spikes.","solutions":["Run pending DB migrations so SELECT * columns match the Invite struct.","Validate orgId (UUID parse) in the handler before calling.","Check connectivity/pool errors in the wrapped cause.","Replace SELECT * with an explicit column list for resilience."],"exampleFix":"// before\nerr := Conn.Select(&invites, \"SELECT * FROM invites WHERE org_id = $1\", orgId)\n\n// after\nerr := Conn.Select(&invites, \"SELECT id, org_id, email, name, inviter_id, org_role_id, accepted_at, created_at FROM invites WHERE org_id = $1\", orgId)","handlingStrategy":"try-catch","validationCode":"if _, err := uuid.Parse(orgId); err != nil {\n    return fmt.Errorf(\"invalid org id %q\", orgId)\n}","typeGuard":null,"tryCatchPattern":"invites, err := db.ListAllInvites(orgId)\nif err != nil {\n    if pgErr, ok := asPG(err); ok && pgErr.Code == \"42P01\" {\n        return fmt.Errorf(\"missing table — check migrations: %w\", err)\n    }\n    return fmt.Errorf(\"list all invites: %w\", err)\n}","preventionTips":["Deploy schema migrations atomically with (or before) new server binaries.","Use explicit column lists in queries instead of SELECT *.","Validate orgId format before calling.","Add retry-with-backoff for transient connection errors in list endpoints.","Alert on wrapped DB errors to catch outages quickly."],"tags":["database","sql","select","list","schema-drift"],"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"}