What I ran into
A checkout update whose body carries payment.instruments draws a bare 500 from the Python sample server. The same update without the payment member returns 200, which is the negative control.
PUT /checkout-sessions/{id}
{"line_items": [{"item": {"id": "bouquet_roses"}, "quantity": 1}],
"payment": {"instruments": [{"id": "pi_1", "type": "card", "handler_id": "h_1"}]}}
HTTP 500 Internal Server Error
Observed against main (00333a8)
Fresh clone, documented setup, seeded flower shop database. Also reproduces at bd06e29, so it predates the recent omit member fixes.
Server log:
File "services/checkout_service.py", line 532, in update_checkout
existing.payment = PaymentResponse(instruments=checkout_req.payment.instruments)
pydantic_core._pydantic_core.ValidationError: ... Input should be a valid dictionary or instance of SelectedPaymentInstrument [type=model_type, input_type=SelectedPaymentInstrument]
The two classes share a name but come from different modules: the parsed request carries payment_instrument_update_request.SelectedPaymentInstrument while PaymentResponse declares the response class payment_instrument.SelectedPaymentInstrument, so construction rejects the instances.
Expected
An update carrying selected instruments should apply them, and any invalid member should draw an in band error in the UCP envelope, the shape this server already uses for its raised errors, never a bare 500.
Where it comes from
The construction dates to #66, when the sdk typed update instruments with the response class, so the pass through worked. python-sdk#64 split the update variant into its own class, published in ucp-sdk 0.4.5, and the first nightly after that release went red on exactly this path. The conformance nightly has failed its two OrderTest cases since Aug 21 for this reason.
Why CI did not catch it
The integration tests never send payment.instruments on update: create sends an empty list and completion uses the complete request path, so the collision site never runs. The cross repo conformance nightly did catch it, red since Aug 21 on OrderTest.test_order_fulfillment_retrieval and test_order_update.
What I ran into
A checkout update whose body carries payment.instruments draws a bare 500 from the Python sample server. The same update without the payment member returns 200, which is the negative control.
Observed against main (00333a8)
Fresh clone, documented setup, seeded flower shop database. Also reproduces at bd06e29, so it predates the recent omit member fixes.
Server log:
The two classes share a name but come from different modules: the parsed request carries payment_instrument_update_request.SelectedPaymentInstrument while PaymentResponse declares the response class payment_instrument.SelectedPaymentInstrument, so construction rejects the instances.
Expected
An update carrying selected instruments should apply them, and any invalid member should draw an in band error in the UCP envelope, the shape this server already uses for its raised errors, never a bare 500.
Where it comes from
The construction dates to #66, when the sdk typed update instruments with the response class, so the pass through worked. python-sdk#64 split the update variant into its own class, published in ucp-sdk 0.4.5, and the first nightly after that release went red on exactly this path. The conformance nightly has failed its two OrderTest cases since Aug 21 for this reason.
Why CI did not catch it
The integration tests never send payment.instruments on update: create sends an empty list and completion uses the complete request path, so the collision site never runs. The cross repo conformance nightly did catch it, red since Aug 21 on OrderTest.test_order_fulfillment_retrieval and test_order_update.