boto/boto3 · error · RetriesExceededError
Max Retries Exceeded
Error message
Max Retries Exceeded
What it means
Raised as boto3.exceptions.RetriesExceededError when the managed download exhausts all retry attempts. download_file catches s3transfer's RetriesExceededError and re-raises it as the boto3 RetriesExceededError (with default message 'Max Retries Exceeded') so callers catching the boto3 exception still work; e.last_exception holds the final underlying exception that retries could not overcome.
Source
Thrown at boto3/s3/transfer.py:491
"""
if isinstance(filename, PathLike):
filename = fspath(filename)
if not isinstance(filename, str):
raise ValueError('Filename must be a string or a path-like object')
subscribers = self._get_subscribers(callback)
future = self._manager.download(
bucket, key, filename, extra_args, subscribers
)
try:
future.result()
# This is for backwards compatibility where when retries are
# exceeded we need to throw the same error from boto3 instead of
# s3transfer's built in RetriesExceededError as current users are
# catching the boto3 one instead of the s3transfer exception to do
# their own retries.
except S3TransferRetriesExceededError as e:
raise RetriesExceededError(e.last_exception)
def _get_subscribers(self, callback):
if not callback:
return None
return [ProgressCallbackInvoker(callback)]
def __enter__(self):
return self
def __exit__(self, *args):
self._manager.__exit__(*args)
class ProgressCallbackInvoker(BaseSubscriber):
"""A back-compat wrapper to invoke a provided callback via a subscriber
:param callback: A callable that takes a single positional argument for
how many bytes were transferred.View on GitHub (pinned to c7b4afac23)
Solutions
- Inspect e.last_exception to see the underlying failure (transport, ClientError code) that retries could not clear.
- Increase retries via botocore Config: boto3.client('s3', config=Config(retries={'max_attempts': 10, 'mode': 'adaptive'})).
- For throttling (503 Slow Down), reduce TransferConfig max_concurrency / max_request_concurrency and switch retry mode to 'adaptive'.
- For network instability, add outer application-level retry with backoff around download_file, and consider resumable ranged GETs.
- Verify region/endpoint and credentials are correct so failures are not due to misconfiguration.
Example fix
// before
s3.download_file('bkt', 'key', '/tmp/out.bin') # raises RetriesExceededError
// after
from botocore.config import Config
cfg = Config(retries={'max_attempts': 10, 'mode': 'adaptive'})
s3 = boto3.client('s3', config=cfg)
from boto3.exceptions import RetriesExceededError
for attempt in range(3):
try:
s3.download_file('bkt', 'key', '/tmp/out.bin')
break
except RetriesExceededError as e:
log.warning('download failed (%s), retrying', e.last_exception) Defensive patterns
Strategy: retry
Validate before calling
# Configure a generous retry budget up front so exhaustion is rare
from botocore.config import Config
cfg = Config(retries={'max_attempts': 10, 'mode': 'adaptive'})
s3 = boto3.client('s3', config=cfg) Type guard
def is_transient(code: str) -> bool:
return code in ('RequestTimeout', 'RequestTimeoutException', 'SlowDown', 'Throttling', 'ThrottlingException', 'InternalError') Try / catch
from boto3.exceptions import RetriesExceededError
import time
for attempt in range(3):
try:
s3.download_file(bucket, key, path)
break
except RetriesExceededError as e:
last = e.last_exception
time.sleep(2 ** attempt)
else:
raise Prevention
- Use Config(retries={'mode':'adaptive'}) to back off under throttling.
- Lower TransferConfig max_concurrency for very large files on flaky links to reduce per-part failures.
- Add outer backoff around download_file for resilient pipelines.
- Verify region/endpoint and credentials so retries are not wasted on misconfiguration.
When it happens
Trigger: Calling s3.download_file(bucket, key, filename) (or Bucket/Object variants) where every retry attempt fails — persistent connection resets, sustained 5xx/timeouts, DNS failures, or a transient error that does not resolve within the configured retry budget. Streaming downloads cannot be retried by botocore, so s3transfer performs the retries and reports exhaustion here.
Common situations: Unstable network or restrictive egress (corporate proxy, NAT timeouts); S3 throttling (503 Slow Down) sustained beyond the retry budget; misconfigured region/endpoint causing repeated connection failures; very large multipart downloads over flaky links.
Related errors
- Fileobj must implement write
- Failed to upload {filename} to {bucket}/{key}: {e}
- Fileobj must implement read
- CRT transfer client is configured but is missing minimum crt
- Either a boto3.Client or s3transfer.manager.TransferManager
AI-assisted analysis of boto/boto3@c7b4afac23 (2026-08-04).
Data as JSON: /data/errors/97f13c304134d272.json.
Report an issue: GitHub.