msal/application.py lines 716-718 mount HTTPAdapter(max_retries=1) as "a minimal retry, better than nothing". For the token endpoint it is nothing: urllib3's Retry(1) keeps the default allowed_methods, which excludes POST, so a connection reset during the token request escapes after one attempt as requests.exceptions.ConnectionError.
Repro over a local TLS server that resets the first /token connection (self-signed cert, verify=False, nothing leaves 127.0.0.1): https://gist.github.com/HardMax71/fd1025dc346b2aefe1291e11cc343d8c
msal 1.38.0 | requests 2.33.0 | urllib3 2.7.0
default http_client (HTTPAdapter(max_retries=1)): ConnectionError escaped, connections after discovery=1: ('Connection aborted.', OSError(22, 'Invalid argument'))
custom http_client, Retry(allowed_methods=None): token=yes | connections after discovery=2
Same on 1.37.0. I know #432 settled on retries being an http-layer concern and a custom http_client being the answer, and that is what we run. This is narrower: the adapter MSAL itself mounts does not do what its comment says. HTTPAdapter(max_retries=Retry(total=1, connect=1, allowed_methods=None, backoff_factor=0.3)) keeps the same one-retry budget and makes it real for the POST. Can send the PR.
msal/application.pylines 716-718 mountHTTPAdapter(max_retries=1)as "a minimal retry, better than nothing". For the token endpoint it is nothing: urllib3'sRetry(1)keeps the defaultallowed_methods, which excludes POST, so a connection reset during the token request escapes after one attempt asrequests.exceptions.ConnectionError.Repro over a local TLS server that resets the first
/tokenconnection (self-signed cert,verify=False, nothing leaves 127.0.0.1): https://gist.github.com/HardMax71/fd1025dc346b2aefe1291e11cc343d8cSame on 1.37.0. I know #432 settled on retries being an http-layer concern and a custom
http_clientbeing the answer, and that is what we run. This is narrower: the adapter MSAL itself mounts does not do what its comment says.HTTPAdapter(max_retries=Retry(total=1, connect=1, allowed_methods=None, backoff_factor=0.3))keeps the same one-retry budget and makes it real for the POST. Can send the PR.