@@ -249,14 +249,19 @@ def _on_timeout():
249249 logger .error (msg )
250250 raise RuntimeError (msg ) from e
251251 except Exception as e :
252- # Record here too (like the OSError branch above) so the
253- # fall-through `raise last_error` always re-raises a real
254- # exception. If a non-OSError/non-webbrowser.Error is raised on
255- # every port, last_error would otherwise stay None and turn
256- # `raise last_error` into `raise None`, masking the real failure
257- # with a confusing TypeError.
258- last_error = e
252+ # A non-OSError/non-webbrowser.Error raised here is not
253+ # port-related (e.g. an OAuth2Error from
254+ # prepare_authorization_request, or an unexpected programming
255+ # bug). Binding the same call to a different local port cannot
256+ # help, so retrying it against every remaining port would only
257+ # multiply latency and log noise and then re-raise the *last*
258+ # attempt's error, obscuring the original failure. Fail fast
259+ # instead, preserving the original exception and traceback via a
260+ # bare `raise`. This also sidesteps the `raise None` hazard that
261+ # the OSError branch guards against, since we never fall through
262+ # to `raise last_error` for this case.
259263 logger .error ("unexpected error: %s" , e )
264+ raise
260265 if self .redirect_port is None :
261266 logger .error (
262267 f"Tried all the ports { self .port_range } for oauth redirect, but can't find free port"
0 commit comments