Skip to content

fix(client): replay request body on paid 402 retry#156

Open
Tleaoo wants to merge 2 commits into
tempoxyz:mainfrom
Tleaoo:fix/client-retry-body
Open

fix(client): replay request body on paid 402 retry#156
Tleaoo wants to merge 2 commits into
tempoxyz:mainfrom
Tleaoo:fix/client-retry-body

Conversation

@Tleaoo

@Tleaoo Tleaoo commented Jun 24, 2026

Copy link
Copy Markdown

Bug: POST/PUT body is dropped on the paid (402) retry

Environment

  • Component: mpp.client.PaymentTransport
  • Affects: any request that carries a body (POST/PUT/PATCH) through the payment flow

Steps to reproduce

  1. Configure a Client with a payment method.
  2. await client.post(url, content=b'{"prompt": "..."}') against an endpoint
    that answers 402 Payment Required.
  3. The transport creates a credential and retries with the Authorization header.

Expected

The retried request reaches the server with the same body as the original —
that's the whole point of the flow: the paid request is the one that must
carry the payload.

Actual

The retry was built reusing the original request's stream:

retry_request = httpx.Request(..., stream=request.stream, ...)

Request bodies are streamed and one-shot. The inner transport already
consumed request.stream when it sent the initial request, so the retry went
out with an empty or malformed body. GET requests have no body, which is why the
existing GET-only tests never caught it.

Fix

Buffer the body before the first dispatch and replay it on the retry:

await request.aread()          # replaces stream with a replayable ByteStream
...
retry_request = httpx.Request(..., content=request.content, ...)

aread() reads the stream once and swaps in a replayable ByteStream, so both
the initial send and the retry transmit identical bytes and a correct
Content-Length.

Test

Added test_paid_retry_replays_request_body — POSTs a body, forces a 402, and
asserts the retried request's content and content-length match the original.
tests/test_client.py: 24 passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant