Skip to content

Concurrent event creation can trigger Prisma P2002 slug conflicts and return 500 errors #311

@Ridanshi

Description

@Ridanshi

Summary

The event slug-generation flow performs a non-atomic read-before-write uniqueness check.

Under concurrent requests creating events with the same name, multiple requests can pass the slug availability check simultaneously and later collide during insert.

The resulting Prisma P2002 unique constraint error is currently returned as a generic 500 Internal Server Error.


Affected File

apps/backend/src/routes/event.ts

Root Cause

The slug generation logic currently performs:

const existing = await app.prisma.event.findUnique({
  where: { slug: finalSlug }
});

inside a loop before the insert occurs.

Later:

await app.prisma.event.create(...)

This creates a classic TOCTOU (time-of-check vs time-of-use) race window.

Two concurrent requests can:

  1. both observe the slug as available,
  2. both attempt insertion,
  3. and cause one request to fail with Prisma P2002.

The current catch block converts this into a generic 500 response.


Production Impact

Concurrent event creation requests with identical names can:

  • return unexpected 500 errors,
  • produce inconsistent client behavior,
  • and force unnecessary retries.

This becomes realistic under:

  • rapid retries,
  • batch imports,
  • concurrent API usage,
  • or multi-client event creation.

Reproduction

Trigger two concurrent event-creation requests using the same event name.

Expected:

  • one request succeeds,
  • the second retries or returns a deterministic conflict response.

Actual:

  • one request succeeds,
  • the second fails with an unhandled Prisma uniqueness conflict → 500.

Proposed Fix

Handle Prisma P2002 slug conflicts explicitly during event creation.

Possible approaches:

  • retry insertion with a new suffix,
  • or remove the pre-check entirely and rely on retry-on-conflict insertion logic.

Suggested handling:

if (error.code === 'P2002') {
  // regenerate slug and retry
}

Acceptance Criteria

  • Concurrent same-name event creation never produces generic 500 responses
  • Prisma slug conflicts are handled deterministically
  • Existing slug behavior remains unchanged
  • Add regression coverage for concurrent insert scenarios

Severity

Medium

This is a realistic concurrency flaw affecting event-creation reliability under concurrent usage patterns.

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