Unhelpful Error for large timeout

Requests should give a better error than `requests.exceptions.ConnectionError: HTTPConnectionPool(host='httpbin.org', port=80): Max retries exceeded with url: /get (Caused by <class 'OSError'>: [Errno 22] Invalid argument)` for inputting a timeout that is too large. Right now it doesn't specify that timeout caused the error, even though it does mention that there is an `Invalid argument` somewhere...

``` python
import requests

r = requests.get('http://httpbin.org/get', timeout=99**99)
```

```
Traceback (most recent call last):
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/packages/urllib3/connectionpool.py", line 493, in urlopen
    body=body, headers=headers)
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/packages/urllib3/connectionpool.py", line 291, in _make_request
    conn.request(method, url, **httplib_request_kw)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/client.py", line 1066, in request
    self._send_request(method, url, body, headers)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/client.py", line 1104, in _send_request
    self.endheaders(body)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/client.py", line 1062, in endheaders
    self._send_output(message_body)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/client.py", line 907, in _send_output
    self.send(msg)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/http/client.py", line 842, in send
    self.connect()
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/packages/urllib3/connection.py", line 106, in connect
    conn = self._new_conn()
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/packages/urllib3/connection.py", line 90, in _new_conn
    (self.host, self.port), self.timeout, *extra_args)
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socket.py", line 509, in create_connection
    raise err
  File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/socket.py", line 500, in create_connection
    sock.connect(sa)
OSError: [Errno 22] Invalid argument

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/adapters.py", line 327, in send
    timeout=timeout
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/packages/urllib3/connectionpool.py", line 543, in urlopen
    raise MaxRetryError(self, url, e)
requests.packages.urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='httpbin.org', port=80): Max retries exceeded with url: /get (Caused by <class 'OSError'>: [Errno 22] Invalid argument)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "test_error.py", line 4, in <module>
    r = requests.get('http://httpbin.org/get', timeout=99**99)
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/api.py", line 55, in get
    return request('get', url, **kwargs)
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/sessions.py", line 456, in request
    resp = self.send(prep, **send_kwargs)
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/sessions.py", line 559, in send
    r = adapter.send(request, **kwargs)
  File "/Users/saul/.virtualenvs/finance-scraper3/lib/python3.4/site-packages/requests/adapters.py", line 375, in send
    raise ConnectionError(e, request=request)
requests.exceptions.ConnectionError: HTTPConnectionPool(host='httpbin.org', port=80): Max retries exceeded with url: /get (Caused by <class 'OSError'>: [Errno 22] Invalid argument)
```


Here's the thing, we don't ever see that `OSError` ourselves. It isn't that we're choosing to raise an unhelpful error, we're raising the error we should be handling. If the socket raises an error, urllib3 catches that and raises a different error (as it should) which we then catch and then use to raise `ConnectionError`. The fact is that we couldn't establish a connection, we cannot introspect every possible cause for that and we certainly cannot introspect the fact that you chose far too large a timeout value. Luckily for you, you are using Python 3 and it helps clarify for you exactly what you did wrong (which you did since you told me what was wrong with your code).

There isn't much we can do in this respect. We're not going to prevent users (like yourself) from shooting themselves in the feet (which precludes us from attempting to determine a maximum timeout value and check for it) and we can't reasonably introspect ever socket-level exception to provide you with something more helpful.


The other issue is that the socket level error is actually coming from the C layer and is hopelessly generic. You've pointed out that it says "Invalid Argument". There are plenty of other arguments to those calls that could have been invalid. The absolutely number one best possible thing we could do is _guess_ at which argument is invalid, which is pretty bad.


@saulshanabrook all of this isn't to say that your request isn't a reasonable one, it's just that there's no practical way to implement it. This is something most of us would _love_ to have. The problem is that there is no way to do this that will be consistent, reliable, and reasonable. This kind of introspection/inference is totally out of the scope of requests unfortunately.


Unless @kennethreitz disagrees, I think this can be closed.


Thank you all so much for the explanations, I tried to dive into the socket C code to see where the actual exception is raised to see how it determines whether a timeout is too large, but I couldn't figure it out.

My only other question is if you guys think this problem is worth mentioning somewhere in the docs. Since I couldn't find anyone else complaining about it, it might not be very common to set timeout too large.


@saulshanabrook the docs aren't meant to be comprehensive, so no this isn't really worth mentioning in the docs. It would be worth writing a blog post about if you feel so inclined. With that indexed by Google, you'll be helping other people with the blog post though. (And sometimes the best documentation is third-party documentation written by people who have experienced problems and are passionate about explaining their solutions or discoveries.)


@sigmavirus24 I just took you up on your suggestion http://www.saulshanabrook.com/requests-timeout-and-odd-traceback/


I'll be tweeting it shortly @saulshanabrook looks like a good post. :+1: