Fix: Duplicate Event Join Error
Branch: fix/duplicate-event-join
Merged into: develop
Date: March 2026
Overview
Fixed a duplicate key value violates unique constraint error that occurred when a user tried to RSVP to an event they had already joined. The event_attendees table enforces a unique constraint on (event_id, user_id), but the upsert call was not specifying a conflict resolution strategy, causing Supabase to throw an exception instead of updating the existing row.
Why It Was Built
Users encountered an unhandled error when tapping the “Join” button a second time (e.g., after app restart, or toggling RSVP status). Without onConflict, Supabase interprets the call as a plain INSERT and fails with a PostgreSQL unique constraint violation. This crashed the RSVP flow and triggered an error report.
What Changed
event_api_service.dart
A single-character fix in the .upsert() call:
// Before
await _client.from('event_attendees').upsert({
'event_id': eventId,
'user_id': userId,
'status': status.name,
});
// After
await _client.from('event_attendees').upsert({
'event_id': eventId,
'user_id': userId,
'status': status.name,
}, onConflict: 'event_id,user_id');onConflict tells Supabase which columns form the unique constraint so the upsert can resolve conflicts with an UPDATE rather than failing.
Architecture Notes
Supabase’s upsert() maps to PostgreSQL’s INSERT ... ON CONFLICT DO UPDATE. Without onConflict, the Supabase client cannot determine the conflict target and defaults to INSERT ... ON CONFLICT DO NOTHING (or raises an error depending on the table definition). Explicitly passing onConflict: 'event_id,user_id' matches the event_attendees_pkey or unique index and correctly updates the status column.