Skip to content

Fix race condition in challenge submission causing duplicate XP #187

@pbrissaud

Description

@pbrissaud

Problem

When submitting a challenge, there's a race condition that can cause duplicate XP transactions and duplicate analytics events.

Root Cause

In server/api/routers/userProgress.ts, the submitChallenge mutation checks if a challenge is already completed:

if (existingProgress?.status === "completed") {
  throw new Error("Challenge already completed");
}

However, if two requests arrive simultaneously (CLI retry, network issues, double-click):

  1. Request 1 checks → not "completed" → continues
  2. Request 2 checks → not "completed" → continues (Request 1 hasn't updated yet)
  3. Request 1 updates status → creates XP transactions + tracks events
  4. Request 2 updates status → creates XP transactions + tracks events again

Impact

  • Users receive 2x XP for a single challenge completion
  • Duplicate challenge_completed events in PostHog
  • Duplicate XP transactions in the database

Proposed Solution

  1. Add unique constraint on (userId, challengeId) in userProgress table
  2. Use upsert pattern with INSERT ... ON CONFLICT DO NOTHING or ON CONFLICT DO UPDATE
  3. Check for existing XP transactions before creating new ones (as additional safety)

Files to Modify

  • server/db/schema/challenge.ts - Add unique index on userProgress
  • server/api/routers/userProgress.ts - Use upsert pattern in submitChallenge
  • Create migration file

Additional Notes

This bug exists independently of the onboarding flow - it affects all challenge submissions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions