Skip to content

fix(tests): catch ConnectionError in WorkOS callback drain calls (Python 3.12+)#6

Merged
igor-ctrl merged 1 commit into
mainfrom
fix/workos-test-flake-py312
May 4, 2026
Merged

fix(tests): catch ConnectionError in WorkOS callback drain calls (Python 3.12+)#6
igor-ctrl merged 1 commit into
mainfrom
fix/workos-test-flake-py312

Conversation

@igor-ctrl

@igor-ctrl igor-ctrl commented May 4, 2026

Copy link
Copy Markdown
Owner

Why

feat/agent-context (#5) merged green on the PR but failed on the merge-to-main run, then again on a manual rerun — same code, different runs. Test:

FAILED tests/test_auth/test_workos_callback_state.py::test_callback_with_wrong_path_is_404
ConnectionResetError: [Errno 104] Connection reset by peer

The failure is on Python 3.12 and 3.13 specifically; 3.11 is forgiving. Pure flake — none of the changes in #5 touched WorkOS auth or the localhost callback handler.

Root cause

The callback-state tests open a localhost listener in a daemon thread, hit it with urlopen, then call urlopen one more time to drain the listener so the thread exits cleanly. Each drain try/except only caught urllib.error.URLError.

Python 3.12+ propagates raw ConnectionResetError unwrapped (when the server thread closes the socket mid-response in http.client._read_status). ConnectionResetError is a sibling of URLError under OSError — not a subclass. So it leaked through the except and crashed the test on 3.12/3.13.

Fix

Widen the except at each of the 5 drain sites in the file from URLError to (URLError, ConnectionError). ConnectionError is the parent of ConnectionResetError, ConnectionAbortedError, etc., so it's semantically pointed (vs. catching the broader OSError). The tests' real assertions live on the threaded login result, not the drain urlopen response — swallowing network errors on these specific calls is safe.

Test plan

  • uv run pytest tests/test_auth/test_workos_callback_state.py -v — 4/4 pass locally on 3.14
  • uv run pytest tests/ -q — full suite 432 pass, 5 skipped (no regression)
  • CI matrix re-runs on this PR (3.11, 3.12, 3.13) all green

…hon 3.12+)

The callback-state tests open a localhost listener in a daemon thread,
hit it via urllib.urlopen(), then call urlopen() once more to drain
the listener so the daemon thread exits cleanly. The drain call only
caught urllib.error.URLError.

Python 3.12+ propagates raw ConnectionResetError unwrapped when the
server thread closes the socket mid-read (in
http.client._read_status). ConnectionResetError is a sibling of
URLError under OSError, not a subclass, so it leaked through and
crashed the test on the matrix's 3.12 / 3.13 jobs while 3.11 was
forgiving. Surfaced as a flake on the feat/agent-context merge to
main; same code passed on the PR run minutes earlier.

Widen the except to (URLError, ConnectionError) at every drain site
in the file. ConnectionError is the parent of all four
ConnectionXxxError variants and is more semantically pointed than a
broad OSError catch. The tests' actual assertions live on the
threaded login result, not the urlopen response, so swallowing
network errors on these specific drain calls is safe.

Verified locally on Python 3.14 (4/4 pass) and via the rerun matrix
once this lands.
@igor-ctrl igor-ctrl merged commit 67d700f into main May 4, 2026
3 checks 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