tests/test_identity_contract.py::ProxyHeaderForwardingTests::test_post_forwards_session_and_content_type_headers_case_insensitively fails intermittently with:
urllib.error.HTTPError: HTTP Error 502: Upstream error: [Errno 54] Connection reset by peer
The product code is behaving correctly; the fault is in the test's stub server.
Its do_POST sends a response and returns without reading the request body. Closing a socket that still holds unread data can make the OS send RST rather than a clean FIN, and an RST can cause the peer's kernel to discard what it has already buffered for that socket — including a response the client received but had not yet read. mcp_proxy then correctly reports the dead connection as a 502, and the test fails.
Because it depends on how much of the body is still unread when the handler returns, it is load-sensitive: the same commit passes one run and fails the next.
Mechanism, reproducible on demand
A stub that replies without consuming the request body loses the exchange outright, deterministically, once the body exceeds the socket buffers. With this test's small body the same close-with-unread-data races the response instead, which is why it only fails sometimes.
One local sample
macOS, Python 3.13, running the file 15 times on a busy machine:
|
failures |
| v0.5.0 as-is |
6 / 15 |
| with the stub reading the body first |
0 / 15 |
Load was not held constant between the two runs, so please treat that as indicative rather than a controlled measurement — the mechanism above is the substantive claim.
The sibling stub in the same class implements only do_GET, which carries no request body, so it cannot hit this.
Fix
Consume the body before replying. Five lines, test-only. PR to follow.
This removes one known source of nondeterministic 502 failures. It is not a claim that the suite becomes deterministic overall.
tests/test_identity_contract.py::ProxyHeaderForwardingTests::test_post_forwards_session_and_content_type_headers_case_insensitivelyfails intermittently with:The product code is behaving correctly; the fault is in the test's stub server.
Its
do_POSTsends a response and returns without reading the request body. Closing a socket that still holds unread data can make the OS send RST rather than a clean FIN, and an RST can cause the peer's kernel to discard what it has already buffered for that socket — including a response the client received but had not yet read.mcp_proxythen correctly reports the dead connection as a 502, and the test fails.Because it depends on how much of the body is still unread when the handler returns, it is load-sensitive: the same commit passes one run and fails the next.
Mechanism, reproducible on demand
A stub that replies without consuming the request body loses the exchange outright, deterministically, once the body exceeds the socket buffers. With this test's small body the same close-with-unread-data races the response instead, which is why it only fails sometimes.
One local sample
macOS, Python 3.13, running the file 15 times on a busy machine:
Load was not held constant between the two runs, so please treat that as indicative rather than a controlled measurement — the mechanism above is the substantive claim.
The sibling stub in the same class implements only
do_GET, which carries no request body, so it cannot hit this.Fix
Consume the body before replying. Five lines, test-only. PR to follow.
This removes one known source of nondeterministic 502 failures. It is not a claim that the suite becomes deterministic overall.