Skip to content

Unbounded line quantity overflows the 32-bit qty columns and returns an opaque 500 #31

@JumpTechCode

Description

@JumpTechCode

Summary

The request models bound line quantities with qty: int = Field(gt=0) but set no upper bound (src/quartermaster/api/schemas.py:17 for OrderLineInput, :110 for ReceiptLineInput). The backing columns are Integer (32-bit) in src/quartermaster/adapters/postgres/tables.py (ordered_qty:97, expected_qty:131, qty_on_hand:74, etc.), and the domain types (OrderLine, ReceiptLine, StockLevel) also impose no upper bound.

A request with qty > 2_147_483_647 passes validation and the domain layer, then fails at INSERT with a numeric-out-of-range error from the driver. That error is not mapped in src/quartermaster/api/errors.py:34-45, so it falls through to the catch-all (_internal_error_handler) and the client receives 500 internal_error for a value it supplied.

Impact

A foreseeable, client-controlled input produces a 500 instead of a 422. Affects create_order, create_receipt, and receive.

Suggested fix

Add an upper bound on the request models, e.g. Field(gt=0, le=2_147_483_647) (or a single domain-defined maximum), so oversized quantities are rejected as 422 at the boundary. Consider mirroring the bound in the domain constructors so the in-memory types and the DB columns agree.

Test gap

No test posts a quantity above the column limit; tests/unit/test_api_schemas.py only covers qty = 0.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions