BerriAI/litellm · error · ImportError
Missing boto3 to call S3. Run 'pip install boto3'.
Error message
Missing boto3 to call S3. Run 'pip install boto3'.
What it means
The S3 download path (reading back a logged object, e.g. for the /spend or log-retrieval features) also does lazy imports of requests + botocore signing classes and raises ImportError when they are missing. Unlike its two siblings, this message correctly says 'call S3'. It fires only when a download is attempted, so installs can run for a long time before hitting it.
Source
Thrown at litellm/integrations/s3_v2.py:589
async def _download_object_from_s3(self, s3_object_key: str) -> dict | None:
"""
Download and parse JSON object from S3.
Args:
s3_object_key: The S3 object key to download
Returns:
Optional[dict]: The parsed JSON object or None if not found/error
"""
try:
import hashlib
import requests
from botocore.auth import S3SigV4Auth
from botocore.awsrequest import AWSRequest
except ImportError:
raise ImportError("Missing boto3 to call S3. Run 'pip install boto3'.")
try:
from litellm.litellm_core_utils.asyncify import asyncify
# Get AWS credentials
asyncified_get_credentials: Final = asyncify(self.get_credentials)
credentials: Final = await asyncified_get_credentials(
aws_access_key_id=self.s3_aws_access_key_id,
aws_secret_access_key=self.s3_aws_secret_access_key,
aws_session_token=self.s3_aws_session_token,
aws_region_name=self.s3_region_name,
aws_session_name=self.s3_aws_session_name,
aws_profile_name=self.s3_aws_profile_name,
aws_role_name=self.s3_aws_role_name,
aws_web_identity_token=self.s3_aws_web_identity_token,
aws_sts_endpoint=self.s3_aws_sts_endpoint,
)
View on GitHub (pinned to 6c2dcb801b)
Solutions
- pip install boto3 requests (or litellm[extra_proxy]) wherever reads happen
- Smoke-test the read path after install: fetch one known s3 object key through the logger
- Pin the deps in your deploy manifest so they cannot be pruned by dependency-resolution tools
Example fix
# before: read endpoint 500s with ImportError: Missing boto3 to call S3 # after # python -m pip install boto3 requests # verify: # python -c "from botocore.auth import S3SigV4Auth; import requests"
Defensive patterns
Strategy: validation
Validate before calling
def can_download_from_s3() -> bool:
try:
import requests
from botocore.auth import S3SigV4Auth # noqa: F401
return True
except ImportError:
return False
if not can_download_from_s3():
raise RuntimeError("boto3/botocore required for S3 log retrieval") Try / catch
try:
obj = await s3_logger.download_data_from_s3(s3_object_key)
except ImportError as e:
if "Missing boto3" in str(e):
obj = None
logger.warning("S3 read path unavailable: install boto3")
else:
raise Prevention
- Smoke-test the S3 read path (not just writes) after deployment
- Pin boto3 in requirements and scan images for it in CI
- Note this import is lazy — a long-running process only discovers the gap on the first read
When it happens
Trigger: Configuring the s3_v2 logger for writes (uploads work because boto3 happens to be present in the writer path's env) and later invoking a read/replay endpoint that triggers download_data_from_s3; mixed environments where only some processes lack botocore.
Common situations: Write-path tested at deploy time but read path (spend reconstruction, log inspection) exercised later; worker containers with trimmed dependencies; local dev with a different venv than the proxy.
Related errors
- Missing boto3 to call bedrock. Run 'pip install boto3'.
- Bedrock event-stream shape could not be loaded from botocore
- Bedrock event-stream shape could not be loaded from botocore
- raw_response.text
- Missing google.cloud package. Run `pip install --upgrade goo
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/c5f8f4e439e1655b.
Report an issue: GitHub.