What I ran into
A checkout create whose line item quantity is -1 returns 201 with negative money in the response:
POST /checkout-sessions
{"line_items": [{"item": {"id": "bouquet_roses"}, "quantity": -1}]}
HTTP 201
totals: subtotal = -3500, total = -3500
quantity 0 is also accepted, on create and update. The same bodies against the Python reference are rejected with a 422, which is the cross implementation control.
Expected
line_item.json declares quantity as an integer with minimum 1 at v2026-04-08, and checkout.md requires additive well known types, subtotal, fulfillment, tax and fee, to have non negative amounts. A create carrying quantity below 1 should draw an in band validation error.
Root cause
The server validates requests with the generated schemas of @ucp-js/sdk (pinned 0.4.3; latest 0.4.4 behaves the same). In both published versions LineItemCreateRequestSchema and LineItemUpdateRequestSchema declare quantity as a bare z.number(), so the schema boundary enforces neither integer nor the minimum, and the raw value flows into the totals math. The js-sdk repo already carries the corrected generation on main, where both sites are z.number().int().gte(1), so the gap is specific to the published packages; a released SDK cut and a version bump here would close it. Reported on the SDK side as the issue filed alongside this one.
Why CI did not catch it
The integration tests always send positive quantities, so the unbounded path never runs. The suite is green on this commit, 152 passing locally.
What I ran into
A checkout create whose line item quantity is -1 returns 201 with negative money in the response:
quantity 0 is also accepted, on create and update. The same bodies against the Python reference are rejected with a 422, which is the cross implementation control.
Expected
line_item.json declares quantity as an integer with minimum 1 at v2026-04-08, and checkout.md requires additive well known types, subtotal, fulfillment, tax and fee, to have non negative amounts. A create carrying quantity below 1 should draw an in band validation error.
Root cause
The server validates requests with the generated schemas of @ucp-js/sdk (pinned 0.4.3; latest 0.4.4 behaves the same). In both published versions LineItemCreateRequestSchema and LineItemUpdateRequestSchema declare quantity as a bare z.number(), so the schema boundary enforces neither integer nor the minimum, and the raw value flows into the totals math. The js-sdk repo already carries the corrected generation on main, where both sites are z.number().int().gte(1), so the gap is specific to the published packages; a released SDK cut and a version bump here would close it. Reported on the SDK side as the issue filed alongside this one.
Why CI did not catch it
The integration tests always send positive quantities, so the unbounded path never runs. The suite is green on this commit, 152 passing locally.