You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since recently I get this error using Python 3.8.6 and OpenSSL 1.1.1d 10 Sep 2019:
Traceback (most recent call last):
File "/home/site/wwwroot/graph/http.py", line 56, in get
response = await self._client.get(*args, **kwargs)
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_client.py", line 1408, in get
return await self.request(
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_client.py", line 1241, in request
response = await self.send(
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_client.py", line 1272, in send
response = await self._send_handling_redirects(
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_client.py", line 1301, in _send_handling_redirects
response = await self._send_handling_auth(
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_client.py", line 1338, in _send_handling_auth
response = await self._send_single_request(request, timeout)
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_client.py", line 1363, in _send_single_request
(
File "/usr/local/lib/python3.8/contextlib.py", line 131, in __exit__
self.gen.throw(type, value, traceback)
File "/home/site/wwwroot/.python_packages/lib/site-packages/httpx/_exceptions.py", line 359, in map_exceptions
raise mapped_exc(message, **kwargs) from None # type: ignore
httpx._exceptions.ReadError: [SSL: APPLICATION_DATA_AFTER_CLOSE_NOTIFY] application data after close notify (_ssl.c:2746)
I don't have such a problem when I'm using OpenSSL 1.1.1 11 Sep 2018.
@flvndh Which version of HTTPX / HTTPCore are you using? Unfortunately in the traceback we can see that map_exceptions shuts down the rest of the previous exceptions (raise ... from None) and so you don't see any additional output that might help figure out what's going on, at least where it's coming from.
Also agree, some information on replicating this would be helpful. Do you hit it consistently? Is it when requesting a particular host? Do you have custom certs involved? Etc… Feel free to look back and fill in the issue template — we have several helpful questions there that you can fill in so anyone looking at this issue can have better context what's going on.
Thank you guys for the quick response. Here is some additional information:
Environment
OS: Linux
Python version: 3.8.6
httpx version: 0.14.1
httpcore version: 0.10.2
OpenSSL version: 1.1.1d
Async environment: asyncio
Event loop: uvloop
HTTP proxy: no
Custom certificates: no
Additional context
The app is deployed as an Azure Function and is a GraphQL endpoint wrapping a REST API. The function receives a list of entity IDs and GraphQL resolves these entities by calling a bunch of REST endpoints behind the scene. Each entity resolution is scheduled as a separate task on the event loop.
As the list of entity IDs grow, I see more and more ConnectionTimeout appearing. I implemented a simple backoff strategy to retry the call after some period of time after such an error but ultimately I get the ReadError above.
I'll try to collect more information about the issue and will keep you posted.
@flvndh Couod you try Horta sing to HTTPX at least 0.14.2? This version shipped #1199 which made it so that the underlying tracebacks from HTTPCore aren't cut off. You'll be able to have more info on where the exception comes from (eg during a read or a write, etc).
Also consider leaving the application running with HTTPX_LOG_LEVEL=trace. That's going to generate lots of logs (a dozen or more per request) but it can also help see more clearly at what stage and in what state the error happens. https://www.python-httpx.org/environment_variables/#httpx_log_level
After 3 timeouts, the exception propagates and the context manager closes the client connection. The problem is that the other tasks are still active, maybe waiting on data to come.
I partially resolved the error by slightly increasing the timeout value but an other option might be to limit the amount of concurrent calls active at the same time.
The problem is that the other tasks are still active, maybe waiting on data to come.
Yes, sounds about right to me. Cleanly cleaning up tasks in asyncio is a bit of a nightmare, to be honest. :-) But it's feasible. Basically you'd need to wrap the gather call around a try/finally; on finally run done, pending = asyncio.wait_for(tasks, timeout=), then cancel everything that's in pending. Then by the exit manager exits all tasks will be properly cancelled already.
(Or you could reach out to things like anyio that provide a clean and sturdy TaskGroup implementation that takes care of this for you. Usually my go-to; it's so easy to mess it up.)
Activity
lovelydinosaur commentedon Nov 23, 2020
I assume it means that the server has terminated the SSL connection, but then sent additional data.
Is it something you're able to replicate?
florimondmanca commentedon Nov 23, 2020
@flvndh Which version of HTTPX / HTTPCore are you using? Unfortunately in the traceback we can see that
map_exceptionsshuts down the rest of the previous exceptions (raise ... from None) and so you don't see any additional output that might help figure out what's going on, at least where it's coming from.Also agree, some information on replicating this would be helpful. Do you hit it consistently? Is it when requesting a particular host? Do you have custom certs involved? Etc… Feel free to look back and fill in the issue template — we have several helpful questions there that you can fill in so anyone looking at this issue can have better context what's going on.
flvndh commentedon Nov 24, 2020
Thank you guys for the quick response. Here is some additional information:
Environment
Additional context
The app is deployed as an Azure Function and is a GraphQL endpoint wrapping a REST API. The function receives a list of entity IDs and GraphQL resolves these entities by calling a bunch of REST endpoints behind the scene. Each entity resolution is scheduled as a separate task on the event loop.
As the list of entity IDs grow, I see more and more
ConnectionTimeoutappearing. I implemented a simple backoff strategy to retry the call after some period of time after such an error but ultimately I get theReadErrorabove.I'll try to collect more information about the issue and will keep you posted.
florimondmanca commentedon Nov 25, 2020
@flvndh Couod you try Horta sing to HTTPX at least 0.14.2? This version shipped #1199 which made it so that the underlying tracebacks from HTTPCore aren't cut off. You'll be able to have more info on where the exception comes from (eg during a read or a write, etc).
Also consider leaving the application running with
HTTPX_LOG_LEVEL=trace. That's going to generate lots of logs (a dozen or more per request) but it can also help see more clearly at what stage and in what state the error happens. https://www.python-httpx.org/environment_variables/#httpx_log_levelflvndh commentedon Nov 25, 2020
@florimondmanca I think I know what happens, please correct me if I'm wrong.
The entry point of the function roughly looks like this:
and the
HTTPClientlike this:After 3 timeouts, the exception propagates and the context manager closes the client connection. The problem is that the other tasks are still active, maybe waiting on data to come.
I partially resolved the error by slightly increasing the timeout value but an other option might be to limit the amount of concurrent calls active at the same time.
florimondmanca commentedon Nov 25, 2020
Yes, sounds about right to me. Cleanly cleaning up tasks in asyncio is a bit of a nightmare, to be honest. :-) But it's feasible. Basically you'd need to wrap the gather call around a try/finally; on finally run
done, pending = asyncio.wait_for(tasks, timeout=), then cancel everything that's inpending. Then by the exit manager exits all tasks will be properly cancelled already.(Or you could reach out to things like
anyiothat provide a clean and sturdyTaskGroupimplementation that takes care of this for you. Usually my go-to; it's so easy to mess it up.)florimondmanca commentedon Nov 25, 2020
@flvndh Ill close for now since I expect you'll be able to sort this out and this isn't really an HTTPX / HTTPCore issue, if that sounds alright!