Skip to content

fix(auth): handle unique-constraint violation in register as 409 Conflict (#55) - #68

Open
ghzhost wants to merge 1 commit into
StellarSend:mainfrom
ghzhost:fix/register-unique-violation-race-55
Open

fix(auth): handle unique-constraint violation in register as 409 Conflict (#55)#68
ghzhost wants to merge 1 commit into
StellarSend:mainfrom
ghzhost:fix/register-unique-violation-race-55

Conversation

@ghzhost

@ghzhost ghzhost commented Sep 2, 2026

Copy link
Copy Markdown

Overview

Closes #55.

When two concurrent POST /api/auth/register requests race on the same email, both could pass the initial SELECT EXISTS(...) query, hash the password via bcrypt (~100-300ms race window), and attempt INSERT INTO users. The database UNIQUE constraint correctly prevents duplication, but the second insert previously triggered a 500 AppError::Database / internal server error rather than 409 Conflict.

Changes

  1. Promoted is_unique_violation(error: &sqlx::Error) -> bool to crate::db::is_unique_violation as a shared helper across the codebase.
  2. Updated services::batch, services::escrow, and services::subscription to use crate::db::is_unique_violation rather than duplicating the helper function.
  3. Wrapped register's INSERT INTO users query with .map_err(...) checking is_unique_violation(&e) and mapping unique constraint violations directly to AppError::Conflict("Email".into()).
  4. Added unit and concurrency database test coverage asserting racing registrations properly return 409 Conflict instead of 500 error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

register has a check-then-insert email race whose loser gets a 500 instead of 409, unlike batch.rs's unique-violation handling

1 participant