From fd74311d2983f1a43d2021cf3d25aa5c8f1b53f3 Mon Sep 17 00:00:00 2001 From: Ishaan Jaffer Date: Mon, 23 Mar 2026 11:30:58 -0700 Subject: [PATCH] fix(bedrock/files): seek before reading IO objects; clear error for binary uploads --- litellm/llms/bedrock/files/transformation.py | 21 ++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/litellm/llms/bedrock/files/transformation.py b/litellm/llms/bedrock/files/transformation.py index fc46ee719ad..dabedd761c8 100644 --- a/litellm/llms/bedrock/files/transformation.py +++ b/litellm/llms/bedrock/files/transformation.py @@ -93,7 +93,10 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig): with open(str(file_content), "rb") as f: content = f.read() elif hasattr(file_content, "read"): # IO[bytes] - # File-like objects need to be read + # Seek to start so a second call (e.g. from transform_create_file_request) + # reads the full content even if the pointer has already advanced. + if hasattr(file_content, "seek"): + file_content.seek(0) content = file_content.read() # Ensure content is string @@ -393,9 +396,17 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig): elif hasattr(extracted_file_data_content, "read") and hasattr( extracted_file_data_content, "seek" ): - # IO[bytes] path (e.g. SpooledTemporaryFile from FastAPI UploadFile) + # IO[bytes] path (e.g. SpooledTemporaryFile from FastAPI UploadFile). + # seek(0) is already called inside _get_content_from_openai_file, but we + # handle this branch directly to surface a clear error for binary uploads. extracted_file_data_content.seek(0) - file_content = extracted_file_data_content.read().decode("utf-8") + raw = extracted_file_data_content.read() + try: + file_content = raw.decode("utf-8") + except UnicodeDecodeError: + raise ValueError( + "Bedrock file uploads require UTF-8 text content. Binary files are not supported." + ) else: raise ValueError("Unsupported file content type") @@ -759,7 +770,9 @@ class BedrockJsonlFilesTransformation: with open(str(file_content), "rb") as f: content = f.read() elif hasattr(file_content, "read"): # IO[bytes] - # File-like objects need to be read + # Seek to start so this helper is idempotent across multiple calls. + if hasattr(file_content, "seek"): + file_content.seek(0) content = file_content.read() # Ensure content is string