boto/boto3 · error · ValueError
Fileobj must implement read
Error message
Fileobj must implement read
What it means
Raised by the injected upload_fileobj() helper (on the S3 client, Bucket, and Object resources) when the Fileobj argument lacks a 'read' attribute. upload_fileobj streams bytes from a file-like object to S3 via the managed transfer manager, and it requires an object that implements read() returning bytes. Passing anything that is not a readable binary stream is rejected up front with this ValueError.
Source
Thrown at boto3/s3/inject.py:660
:type Key: str
:param Key: The name of the key to upload to.
:type ExtraArgs: dict
:param ExtraArgs: Extra arguments that may be passed to the
client operation. For allowed upload arguments see
:py:attr:`boto3.s3.transfer.S3Transfer.ALLOWED_UPLOAD_ARGS`.
:type Callback: function
:param Callback: A method which takes a number of bytes transferred to
be periodically called during the upload.
:type Config: boto3.s3.transfer.TransferConfig
:param Config: The transfer configuration to be used when performing the
upload.
"""
if not hasattr(Fileobj, 'read'):
raise ValueError('Fileobj must implement read')
subscribers = None
if Callback is not None:
subscribers = [ProgressCallbackInvoker(Callback)]
config = Config
if config is None:
config = TransferConfig()
with create_transfer_manager(self, config) as manager:
future = manager.upload(
fileobj=Fileobj,
bucket=Bucket,
key=Key,
extra_args=ExtraArgs,
subscribers=subscribers,
)
return future.result()View on GitHub (pinned to c7b4afac23)
Solutions
- Pass an already-opened binary file handle: with open(path, 'rb') as f: s3.upload_fileobj(f, bucket, key).
- If you only have a filename/path, use s3.upload_file(filename, bucket, key) instead of upload_fileobj.
- If you have an in-memory bytes payload, wrap it with io.BytesIO(data) before calling upload_fileobj.
- Ensure you are not passing a text-mode handle or a string.
Example fix
// before
s3.upload_fileobj('data.txt', 'mybucket', 'key') # wrong: string, not file-like
// after
with open('data.txt', 'rb') as f:
s3.upload_fileobj(f, 'mybucket', 'key') Defensive patterns
Strategy: type-guard
Validate before calling
if not hasattr(fileobj, 'read'):
raise TypeError('upload_fileobj requires a readable file-like object')
s3.upload_fileobj(fileobj, bucket, key) Type guard
def is_readable_fileobj(obj) -> bool:
return hasattr(obj, 'read') and callable(getattr(obj, 'read')) Try / catch
try:
s3.upload_fileobj(fileobj, bucket, key)
except ValueError as e:
if 'must implement read' in str(e):
with open(path, 'rb') as f:
s3.upload_fileobj(f, bucket, key) Prevention
- Always open upload sources with open(path, 'rb').
- Use upload_file(path, ...) when you only have a filename, and upload_fileobj(f, ...) when you have a handle.
- Wrap in-memory payloads with io.BytesIO before uploading.
When it happens
Trigger: Calling s3.upload_fileobj(Fileobj, Bucket, Key) / bucket.upload_fileobj(...) where Fileobj is a path string (meant for upload_file instead), a bytes object, a file opened in text mode ('r' without 'b'), a StringIO, None, or any object without a read method.
Common situations: Confusing upload_file (takes a filename string) with upload_fileobj (takes an open file); opening the file with open(path) (text mode) and forgetting 'rb'; passing the raw value returned from requests/urllib without wrapping it; passing a pathlib.Path object.
Related errors
- Fileobj must implement write
- Filename must be a string or a path-like object
- Either a boto3.Client or s3transfer.manager.TransferManager
- Manager cannot be provided with client, config, nor osutil.
- Failed to upload {filename} to {bucket}/{key}: {e}
AI-assisted analysis of boto/boto3@c7b4afac23 (2026-08-04).
Data as JSON: /data/errors/194f6b08dab5d29e.json.
Report an issue: GitHub.