fix(bedrock): use actual file size when Content-Length missing (#36388)

This commit is contained in:
Lavya Tandel 2026-08-10 23:56:49 +05:30
parent dee667edb7
commit 2d2b32c3f8
2 changed files with 65 additions and 1 deletions

View file

@ -861,6 +861,9 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig):
)
litellm_params["upload_url"] = api_base
# Store file size for response transformation (S3 PUT response
# doesn't include Content-Length, so we pass it through).
litellm_params["_file_content_size"] = len(file_content) if isinstance(file_content, (str, bytes)) else 0
# Return a dict that tells the HTTP handler exactly what to do
return {
@ -1024,6 +1027,12 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig):
# S3 PUT object returns ETag and other metadata in headers
content_length: Final = response_headers.get("Content-Length", "0")
# S3 PUT responses may not include Content-Length, so fall back
# to the actual content size captured during request transformation.
file_size: int = int(content_length) if content_length.isdigit() else 0
if file_size == 0:
file_size = litellm_params.get("_file_content_size", 0)
# Use the actual upload URL that was used for the S3 upload
upload_url: Final = litellm_params.get("upload_url")
file_id: str = ""
@ -1038,7 +1047,7 @@ class BedrockFilesConfig(BaseAWSLLM, BaseFilesConfig):
filename=filename,
created_at=int(time.time()), # Current timestamp
status="uploaded",
bytes=int(content_length) if content_length.isdigit() else 0,
bytes=file_size,
object="file",
)

View file

@ -2038,6 +2038,61 @@ class TestBedrockFilesS3SignatureEncoding:
headers=signed["headers"],
)
def test_transform_create_file_response_bytes_from_content_length(self):
"""bytes should reflect actual file size when Content-Length is present."""
import httpx
from litellm.llms.bedrock.files.transformation import BedrockFilesConfig
raw_response = httpx.Response(
status_code=200,
headers={"Content-Length": "4096"},
content=b"",
request=httpx.Request(
"PUT",
"https://s3.us-east-1.amazonaws.com/my-bucket/litellm-bedrock-files-anthropic.claude-3-5-sonnet-20240620-v1:0-abc123.jsonl",
),
)
result = BedrockFilesConfig().transform_create_file_response(
model=None,
raw_response=raw_response,
logging_obj=MagicMock(),
litellm_params={},
)
assert result.bytes == 4096
def test_transform_create_file_response_bytes_falls_back_to_content_size(self):
"""When S3 PUT response omits Content-Length, bytes should fall back
to the actual content size captured during request transformation.
Regression test for #36388.
"""
import httpx
from litellm.llms.bedrock.files.transformation import BedrockFilesConfig
raw_response = httpx.Response(
status_code=200,
# S3 PUT responses typically omit Content-Length
headers={},
content=b"",
request=httpx.Request(
"PUT",
"https://s3.us-east-1.amazonaws.com/my-bucket/litellm-bedrock-files-anthropic.claude-3-5-sonnet-20240620-v1:0-abc123.jsonl",
),
)
result = BedrockFilesConfig().transform_create_file_response(
model=None,
raw_response=raw_response,
logging_obj=MagicMock(),
litellm_params={"_file_content_size": 2048},
)
assert result.bytes == 2048
def test_file_content_signs_spaced_object_key_the_way_s3_does(
self, monkeypatch: pytest.MonkeyPatch
) -> None: