From 8dee0b6ff5c9c3068efb0ea7c1ae2cf23e30dd30 Mon Sep 17 00:00:00 2001 From: Vadym Samoilenko Date: Fri, 1 May 2026 14:35:09 +0100 Subject: [PATCH] fix(membership): guard against missing/invalid role_in_org in membership docs list_org_members and _membership_from_doc used bracket access on role_in_org which raises KeyError if the field is absent (old docs or direct DB inserts). Also handles ValueError if the stored value doesn't match a valid OrgRole. Falls back to OrgRole.MEMBER in both cases. Fixes 500 on GET /organizations/{org_id}/members. Co-Authored-By: Claude Sonnet 4.6 --- backend/app/services/membership_service.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/backend/app/services/membership_service.py b/backend/app/services/membership_service.py index fce4b02..8376184 100644 --- a/backend/app/services/membership_service.py +++ b/backend/app/services/membership_service.py @@ -13,11 +13,16 @@ def _now() -> datetime: def _membership_from_doc(doc: dict) -> Membership: + raw_role = doc.get("role_in_org", "member") + try: + role = OrgRole(raw_role) + except ValueError: + role = OrgRole.MEMBER return Membership( id=str(doc["_id"]), - user_id=doc["user_id"], - organization_id=doc["organization_id"], - role_in_org=OrgRole(doc["role_in_org"]), + user_id=doc.get("user_id", ""), + organization_id=doc.get("organization_id", ""), + role_in_org=role, created_at=doc.get("created_at"), created_by=doc.get("created_by"), ) @@ -110,13 +115,18 @@ async def list_org_members( details = [] async for doc in db.memberships.aggregate(pipeline): u = doc["user_doc"] + raw_role = doc.get("role_in_org", "member") + try: + role = OrgRole(raw_role) + except ValueError: + role = OrgRole.MEMBER details.append( MemberDetail( membership_id=str(doc["_id"]), - user_id=doc["user_id"], + user_id=doc.get("user_id", ""), email=u.get("email", ""), full_name=u.get("full_name", ""), - role_in_org=OrgRole(doc["role_in_org"]), + role_in_org=role, created_at=doc.get("created_at"), ) )