Skip to content

Reject ClientTimeout(total=0) in v4, use None to disable timeouts#12044

Merged
Dreamsorcerer merged 6 commits intoaio-libs:masterfrom
veeceey:fix/issue-11859
Feb 16, 2026
Merged

Reject ClientTimeout(total=0) in v4, use None to disable timeouts#12044
Dreamsorcerer merged 6 commits intoaio-libs:masterfrom
veeceey:fix/issue-11859

Conversation

@veeceey
Copy link
Copy Markdown
Contributor

@veeceey veeceey commented Feb 8, 2026

Fixes #11859

Instead of normalizing total=0 to None, this PR removes support for ClientTimeout(total=0) entirely in v4.

asyncio.loop.start_tls() only accepts None or a positive number for ssl_handshake_timeout, so passing total=0 caused a ValueError. Rather than working around it, we now reject total=0 upfront with a clear error message directing users to use None instead.

The backport to 3.14 (#12067) keeps the normalization approach for backwards compatibility.

Changes:

  • Add __post_init__ validation to ClientTimeout that rejects total=0
  • Revert the timeout.total or None workaround in connector.py
  • Replace functional TLS test with validation tests
  • Update changelog

@psf-chronographer psf-chronographer bot added the bot:chronographer:provided There is a change note present in this PR label Feb 8, 2026
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 8, 2026

Merging this PR will not alter performance

✅ 59 untouched benchmarks


Comparing veeceey:fix/issue-11859 (8c58af6) with master (32924e8)

Open in CodSpeed

@codecov
Copy link
Copy Markdown

codecov bot commented Feb 9, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.76%. Comparing base (100e5ed) to head (8c58af6).
⚠️ Report is 11 commits behind head on master.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #12044      +/-   ##
==========================================
+ Coverage   98.69%   98.76%   +0.06%     
==========================================
  Files         127      127              
  Lines       44667    44684      +17     
  Branches     2372     2372              
==========================================
+ Hits        44086    44130      +44     
+ Misses        412      393      -19     
+ Partials      169      161       -8     
Flag Coverage Δ
CI-GHA 98.61% <100.00%> (+0.04%) ⬆️
OS-Linux 98.35% <100.00%> (+<0.01%) ⬆️
OS-Windows 96.69% <100.00%> (+0.40%) ⬆️
OS-macOS 97.58% <100.00%> (?)
Py-3.10.11 97.13% <100.00%> (?)
Py-3.10.19 97.62% <100.00%> (+0.66%) ⬆️
Py-3.11.14 97.82% <100.00%> (-0.01%) ⬇️
Py-3.11.9 97.35% <100.00%> (?)
Py-3.12.10 97.44% <100.00%> (?)
Py-3.12.12 97.92% <100.00%> (-0.01%) ⬇️
Py-3.13.12 98.16% <100.00%> (+0.68%) ⬆️
Py-3.14.3 98.13% <100.00%> (+0.22%) ⬆️
Py-3.14.3t 97.21% <100.00%> (-0.03%) ⬇️
Py-pypy3.11.13-7.3.20 97.36% <100.00%> (?)
VM-macos 97.58% <100.00%> (?)
VM-ubuntu 98.35% <100.00%> (+<0.01%) ⬆️
VM-windows 96.69% <100.00%> (+0.40%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@webknjaz
Copy link
Copy Markdown
Member

According to the issue, Sam suggested not supporting this in v4.

@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 12, 2026

Right -- Sam mentioned considering removing 0 support in v4. This fix is for the current behavior where the docs say "None or 0 disables the timeout" (client_quickstart.html#aiohttp-client-timeouts). Since 0 is currently documented as valid, passing it through shouldn't crash with a ValueError.

Happy to add a deprecation warning for total=0 as well if that helps with the v4 transition, or I can leave that for a separate discussion.

@Dreamsorcerer
Copy link
Copy Markdown
Member

Happy to add a deprecation warning for total=0 as well if that helps with the v4 transition, or I can leave that for a separate discussion.

If we're good with dropping support for 0, then I'd like this PR to be moved to the 3.14 branch, and a new PR to master (v4) that removes it.

@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 14, 2026

Makes sense, I'll retarget this to the 3.14 branch with the fix + deprecation warning for total=0, and open a separate PR against master that removes 0 support entirely. Will update shortly.

@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 14, 2026

Created #12067 against the 3.14 branch with the normalization fix.

I'll rework this PR to remove total=0 support for v4 -- will update the ClientTimeout validation to reject 0 with a clear error message, update the docs, and adjust the tests accordingly.

veeceey and others added 5 commits February 13, 2026 22:58
When `ClientTimeout(total=0)` is used (meaning no timeout), the value `0`
was passed directly to `asyncio.loop.start_tls()` as `ssl_handshake_timeout`,
which requires either `None` or a positive number. This caused a `ValueError`.

The fix converts `0` to `None` using `timeout.total or None` before passing
it to `start_tls()`, aligning with aiohttp's documented behavior where both
`None` and `0` mean "no timeout".

Fixes aio-libs#11859

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…loop.start_tls

The Python intersphinx inventory lists asyncio.loop.start_tls as a
py:method, not py:func. Using :py:func: causes an unresolved reference
warning, which fails the build due to Sphinx's -W flag.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
Rewrite test_start_tls_with_zero_total_timeout to use a real TLS
server/client instead of mocking internals. This tests actual framework
behavior — making an HTTPS request with ClientTimeout(total=0) should
succeed without raising ValueError.

Also fix changelog to use :exc: Sphinx reference for ValueError.
Instead of normalizing 0 to None for ssl_handshake_timeout, validate
upfront that total=0 is not passed. The docs previously said 0 or None
disables the timeout, but asyncio.loop.start_tls only accepts None or
positive values. For v4, we drop the 0 support entirely with a clear
error message directing users to use None instead.

Fixes aio-libs#11859
@veeceey veeceey changed the title Fix ValueError with ClientTimeout(total=0) in TLS connections Reject ClientTimeout(total=0) in v4, use None to disable timeouts Feb 14, 2026
@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 14, 2026

Reworked this for v4 as discussed. Instead of normalizing 0 to None, the PR now:

  • Adds __post_init__ validation to ClientTimeout that rejects total=0 with a clear error message pointing to None
  • Reverts the timeout.total or None workaround in connector.py (no longer needed since 0 can't reach it)
  • Replaces the functional TLS test with simple validation tests

The 3.14 backport (#12067) keeps the normalization approach for backwards compatibility.

@Dreamsorcerer
Copy link
Copy Markdown
Member

Appears to be a test to update.

The test_tcp_connector_cancel_dns_error_captured test was still using
ClientTimeout(0) which now raises ValueError since total=0 is no longer
supported. Use default ClientTimeout() (total=None) instead.
@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 15, 2026

Updated the test, thanks for pointing that out.

@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 16, 2026

Hi @Dreamsorcerer @webknjaz, this has been reworked for v4 as discussed — ClientTimeout now rejects total=0 in post_init with a clear error pointing to None, and I've updated the test that was flagged. The 3.14 backport is in #12067. Ready for another look when you get a chance!

@Dreamsorcerer Dreamsorcerer added the backport:skip Skip backport bot label Feb 16, 2026
@Dreamsorcerer Dreamsorcerer merged commit 1c472b5 into aio-libs:master Feb 16, 2026
42 of 43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport:skip Skip backport bot bot:chronographer:provided There is a change note present in this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exception trying to create a TLS connection with ClientTimeout(total=0)

3 participants