Skip to content

Treevite invite race condition creates orphaned user/participant records #2489

@jucor

Description

@jucor

Bug: Treevite invite race condition creates orphaned user/participant records

Summary

When two requests race on the same treevite invite code, the "loser" (the request that loses the UPDATE ... WHERE status = 0 race) returns polis_err_treevite_invite_race_condition — but the user and participant records it created are never cleaned up.

Location

server/src/invites/treevites.ts, lines ~410-431 in handleAcceptInvite:

  1. Lines 410-419: Create anonymous user + participant (before checking if the invite is still available)
  2. Lines 423-426: UPDATE treevite_invites SET status = 1 ... WHERE id = ($2) AND status = 0 RETURNING id
  3. Lines 428-431: If UPDATE returns no rows → return 400 error, but the user/participant from step 1 remain in the DB

Impact

  • Orphaned users and participants rows accumulate over time
  • conversations.participant_count is incremented by the pid_auto trigger but never decremented
  • Low severity in practice (requires exact timing of concurrent invite acceptance)

Suggested fix

Move user/participant creation (step 1) to after the successful UPDATE (step 2). This way, the loser never creates records that need cleanup.

Discovered while

Investigating the flaky treevite.test.ts test "should handle multiple participants trying to use same invite" — the test expected polis_err_treevite_invalid_or_used_invite but sometimes received polis_err_treevite_invite_race_condition. Test fix in the associated PR.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions