fix(PROJ-11): BUG-24 — duplicate team-member add returned 500, not 409

First attempt checked err.code, which is undefined — drizzle-orm wraps
the raw pg error (the one that actually has .code = '23505' for a
unique violation) in .cause. Live-tested and caught before assuming
the fix worked from code review alone. Now checks err.cause?.code
first, falls back to err.code.

Verified: first add 201, duplicate add 409 "Member is already on this
team" instead of 500.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0143yYvjesjHndBACoweyK67
This commit is contained in:
patrickandClaude Sonnet 5 committed 2026-09-11 23:55:29 +02:00
1 parent 5c2e09b36d
commit 94b25bcc36
2 files changed
+22 -1

No files matched your search

+14 -1
View File
@@ -152,7 +152,20 @@ export async function teamRoutes(app: FastifyInstance) {
return reply.code(403).send({ error: "Forbidden" });
}
await db.insert(teamMembers).values({ teamId, memberId });
try {
await db.insert(teamMembers).values({ teamId, memberId });
} catch (err) {
// BUG-24: duplicate add used to fall through to the global error handler
// as a generic 500 — no longer leaking SQL (BUG-19 fix), but still the
// wrong status for "this member is already on this team".
// drizzle-orm wraps the raw pg error (which has the .code) in .cause.
const pgCode = (err as { code?: string; cause?: { code?: string } }).cause?.code
?? (err as { code?: string }).code;
if (pgCode === "23505") {
return reply.code(409).send({ error: "Member is already on this team" });
}
throw err;
}
const [room] = await db
.select({ matrixRoomId: chatRooms.matrixRoomId })
+8
View File
@@ -934,3 +934,11 @@ Live verifiziert: Token liefert vor dem Logout `200` auf `/account/whoami`, nach
### Status
**Production-ready: JA** — beide Auflagen aus Runde 4 sind erledigt und live verifiziert. Verbleibend nur noch bewusst akzeptierte/dokumentierte Punkte (BUG-11, BUG-2/20-Restrisiko) und der manuelle iOS-Safari-Tastatur-Test.
## BUG-24-Fix (2026-09-11)
**Behoben, live verifiziert — brauchte zwei Versuche.** Doppeltes Hinzufügen eines Mitglieds zum selben Team lieferte `500` statt `409`. Erster Fix-Versuch (`(err as { code }).code === "23505"`) griff nicht — Live-Test zeigte weiterhin `500`. Ursache: `drizzle-orm` wrappt den rohen `pg`-Fehler (der den `.code` trägt) in `.cause`, nicht direkt auf dem geworfenen `DrizzleQueryError`. Fix geprüft `err.cause?.code` zuerst, fällt auf `err.code` zurück.
Live verifiziert: erstes Hinzufügen `201`, zweites (Duplikat) `409 {"error":"Member is already on this team"}` statt `500`.
**Lehre, konsistent mit BUG-23:** ein Fix, der nur nach Code-Lesen plausibel aussieht, ist erst durch einen echten Request gegen die Fehlerbehandlung verifiziert — die Fehler-Wrapping-Tiefe von ORM-Bibliotheken lässt sich am Typsystem nicht ablesen (`err.code` kompiliert anstandslos, obwohl es zur Laufzeit `undefined` ist).