diff --git a/lib/spack/spack/oci/opener.py b/lib/spack/spack/oci/opener.py index 0717101274..53535b85ed 100644 --- a/lib/spack/spack/oci/opener.py +++ b/lib/spack/spack/oci/opener.py @@ -418,18 +418,27 @@ def ensure_status(request: urllib.request.Request, response: HTTPResponse, statu ) -def default_retry(f, retries: int = 3, sleep=None): +def default_retry(f, retries: int = 5, sleep=None): sleep = sleep or time.sleep def wrapper(*args, **kwargs): for i in range(retries): try: return f(*args, **kwargs) - except urllib.error.HTTPError as e: + except (urllib.error.URLError, TimeoutError) as e: # Retry on internal server errors, and rate limit errors # Potentially this could take into account the Retry-After header # if registries support it - if i + 1 != retries and (500 <= e.code < 600 or e.code == 429): + if i + 1 != retries and ( + ( + isinstance(e, urllib.error.HTTPError) + and (500 <= e.code < 600 or e.code == 429) + ) + or ( + isinstance(e, urllib.error.URLError) and isinstance(e.reason, TimeoutError) + ) + or isinstance(e, TimeoutError) + ): # Exponential backoff sleep(2**i) continue