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

  1. pip install boto3 requests (or litellm[extra_proxy]) wherever reads happen
  2. Smoke-test the read path after install: fetch one known s3 object key through the logger
  3. 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

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


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/c5f8f4e439e1655b. Report an issue: GitHub.