boto/boto3 · error · S3UploadFailedError

Failed to upload {filename} to {bucket}/{key}: {e}

Error message

Failed to upload {filename} to {bucket}/{key}: {e}

What it means

Raised as S3UploadFailedError when the underlying managed upload's future.result() raises a botocore ClientError. upload_file wraps any ClientError originating from PutObject/CreateMultipartUpload/UploadPart/CompleteMultipartUpload into S3UploadFailedError so callers have a single boto3 exception to catch for upload failures; the message includes the local filename, target bucket/key, and the wrapped error. The root cause is whatever the S3 service (or transport) rejected.

Source

Thrown at boto3/s3/transfer.py:458

            :py:meth:`S3.Client.upload_fileobj`
        """
        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.upload(
            filename, bucket, key, extra_args, subscribers
        )
        try:
            future.result()
        # If a client error was raised, add the backwards compatibility layer
        # that raises a S3UploadFailedError. These specific errors were only
        # ever thrown for upload_parts but now can be thrown for any related
        # client error.
        except ClientError as e:
            raise S3UploadFailedError(
                f"Failed to upload {filename} to {bucket}/{key}: {e}"
            )

    def download_file(
        self, bucket, key, filename, extra_args=None, callback=None
    ):
        """Download an S3 object to a file.

        Variants have also been injected into S3 client, Bucket and Object.
        You don't have to use S3Transfer.download_file() directly.

        .. seealso::
            :py:meth:`S3.Client.download_file`
            :py:meth:`S3.Client.download_fileobj`
        """
        if isinstance(filename, PathLike):
            filename = fspath(filename)
        if not isinstance(filename, str):

View on GitHub (pinned to c7b4afac23)

Solutions

  1. Inspect e.last_exception / the wrapped ClientError response['Error']['Code'] and response['Error']['Message'] to identify the exact S3 failure.
  2. For AccessDenied, verify the IAM principal has s3:PutObject (and kms:GenerateDataKey if SSE-KMS) on the target bucket, and that the bucket policy does not deny it.
  3. For NoSuchBucket, confirm the bucket name and region and that the client is in the right region.
  4. For throttling/timeouts, increase TransferConfig max_concurrency/retry counts or add exponential backoff.
  5. Wrap the call in try/except S3UploadFailedError and retry idempotently on transient codes.

Example fix

// before
s3.upload_file('/tmp/data.bin', 'bkt', 'key')  # surfaces as S3UploadFailedError

// after
from boto3.exceptions import S3UploadFailedError
try:
    s3.upload_file('/tmp/data.bin', 'bkt', 'key')
except S3UploadFailedError as e:
    code = e.args[0].split(':')[-1]  # or parse the wrapped ClientError
    log.error('upload failed: %s', e)
    raise
Defensive patterns

Strategy: try-catch

Validate before calling

# Pre-flight: confirm bucket/region and credentials resolve before upload
sts = boto3.client('sts')
sts.get_caller_identity()  # raises if credentials are missing
client = boto3.client('s3', region_name=region)
client.head_bucket(Bucket=bucket)  # raises if bucket/permission wrong

Type guard

def can_put_object(client, bucket, key) -> bool:
    try:
        client.head_bucket(Bucket=bucket)
        return True
    except Exception:
        return False

Try / catch

from boto3.exceptions import S3UploadFailedError
try:
    s3.upload_file(filename, bucket, key)
except S3UploadFailedError as e:
    cause = e.args[0]
    # parse the wrapped ClientError code from cause and branch on it
    raise

Prevention

When it happens

Trigger: Calling s3.upload_file(filename, bucket, key) (or the Bucket/Object variants) and hitting a ClientError: NoSuchBucket, AccessDenied/403, RequestTimeout, slow-down/503, invalid ExtraArgs, signature/credential failures, or a connection reset during a multipart upload.

Common situations: Missing IAM s3:PutObject permission; wrong bucket name or region; expired temporary credentials; uploading to a bucket with object-lock/KMS where the key policy or KMS grant denies the caller; transient throttling on a busy bucket.

Related errors


AI-assisted analysis of boto/boto3@c7b4afac23 (2026-08-04). Data as JSON: /data/errors/3dfbb5c6f5ab92a2.json. Report an issue: GitHub.