Skip to content

[Bug]: Assigning a kit to custody concurrently returns a 500 instead of a conflict error #2821

Description

@evanmarshall

What happened?

When two users assign the same kit to custody at the same time, one request fails with a generic 500 server error instead of a clear "kit already in custody" conflict message. The kit is still assigned only once (data integrity holds), but the loser of the race sees an unhandled server error.

Steps to reproduce:

  1. Have a kit that is available (not in custody).
  2. Fire two "assign custody" requests for that kit at nearly the same moment (two operators, or a double-click / retry).
  3. One request wins. The other hits the unique constraint on KitCustody and returns a 500.

In bulkAssignKitCustody (apps/webapp/app/modules/kit/service.server.ts), the assignment runs tx.kitCustody.createMany(...) at line 2416. When a concurrent assignment already created the row, Prisma throws a P2002 unique-constraint violation. That falls through to the outer catch at line 2540, which rethrows a ShelfError with the generic message "Something went wrong while bulk checking out kits" and no explicit status or shouldBeCaptured: false. The result is a captured 500 and an error-report entry for what is really an expected concurrency conflict.

What is the expected behaviour?

A concurrent double-assignment should return a handled 4xx (409 conflict or a 400 "kit unavailable") with a clear message, and should not be captured as an error. The transaction rollback and single-assignment behaviour already work correctly; only the error classification needs fixing. The smallest fix is to recognize the P2002 on the KitCustody uniqueness constraint in this catch and throw a handled conflict error with shouldBeCaptured: false, mirroring how other expected-conflict paths in this file are already handled (for example around lines 2354-2395).

Version: Self-hosted (reproduced against main @ 7e139f5)

Found while running Ito (AI code review, free for open source) against recently merged PRs — full analysis: https://app.ito.ai/share/a4681a63-43f5-47c3-8a22-c664ed8acce7.

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