BerriAI/litellm · error · ValueError

file_id must be a managed LiteLLM S3 file id

Error message

file_id must be a managed LiteLLM S3 file id

What it means

validate_managed_cloud_file_id accepts only ids that decode to LiteLLM-managed ids (base64url payloads with the LITELM_MANAGED_FILE_ID_PREFIX) or literal 's3://' URIs; anything else is rejected to prevent unvalidated file-id injection into S3 key resolution.

Source

Thrown at litellm/llms/bedrock/files/transformation.py:175

    Resolve a Bedrock file id to its S3 URI.

    Accepts either a base64-encoded LiteLLM unified file id (whose decoded
    form carries `llm_output_file_id,s3://...`) or a direct `s3://` URI.
    """
    try:
        padded: Final = file_id + "=" * (-len(file_id) % 4)
        decoded: Final = base64.urlsafe_b64decode(padded).decode()

        if decoded.startswith(SpecialEnums.LITELM_MANAGED_FILE_ID_PREFIX.value):
            if "llm_output_file_id," in decoded:
                return decoded.split("llm_output_file_id,")[1].split(";")[0]
    except Exception:
        pass

    if file_id.startswith("s3://"):
        return file_id

    raise ValueError("file_id must be a managed LiteLLM S3 file id")


def get_configured_s3_bucket_name(litellm_params: Mapping[str, object]) -> str:
    """
    Resolve the server-configured S3 bucket for Bedrock file operations.

    Only trusts the immutable server-side credential snapshot or the
    environment; never a request-supplied param, since the bucket is what
    `validate_managed_cloud_file_id` checks file ids against.
    """
    trusted_model_credentials: Final = litellm_params.get("_litellm_internal_model_credentials")
    bucket_name: str | None = None
    if isinstance(trusted_model_credentials, MappingProxyType):
        snapshot: Final[dict[str, object]] = {}
        snapshot.update(trusted_model_credentials)  # any-ok: untyped snapshot
        bucket_name = _TrustedS3ModelCredentials.model_validate(snapshot).s3_bucket_name
    bucket_name = bucket_name or os.getenv("AWS_S3_BUCKET_NAME")
    if not bucket_name:

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Use the id returned by litellm's create-file endpoint for Bedrock (an s3:// URI or a managed LiteLLM id).
  2. If you own the object, pass the full 's3://bucket/key' URI directly.
  3. Re-upload the file through litellm to obtain a valid managed id.

Example fix

# before
handler.file_content(FileContentRequest(file_id="file-1a2b3c"))

# after
handler.file_content(FileContentRequest(file_id="s3://my-bucket/bedrock-managed-batch/model-uuid.jsonl"))
Defensive patterns

Strategy: type-guard

Validate before calling

import base64
from litellm.constants import SpecialEnums  # prefix enum

def is_managed_or_s3_id(file_id: str) -> bool:
    if file_id.startswith("s3://"):
        return True
    try:
        padded = file_id + "=" * (-len(file_id) % 4)
        return base64.urlsafe_b64decode(padded).decode().startswith(
            SpecialEnums.LITELM_MANAGED_FILE_ID_PREFIX.value
        )
    except Exception:
        return False

Type guard

def is_usable_bedrock_file_id(file_id: str) -> bool:
    return file_id.startswith("s3://") or is_managed_or_s3_id(file_id)

Try / catch

try:
    content = handler.file_content(FileContentRequest(file_id=fid))
except ValueError as e:
    if "managed LiteLLM S3 file id" in str(e):
        raise BadUserInput(fid)  # 400 to client
    raise

Prevention

When it happens

Trigger: Passing a raw OpenAI file id (e.g. 'file-abc123') or arbitrary string as file_id to Bedrock file content/operations instead of the managed id returned by litellm's file create, and not an s3:// URI.

Common situations: Migrating from OpenAI to Bedrock-backed files and reusing OpenAI ids; client apps storing provider-agnostic ids; passing an id after the managed-prefix format changed between litellm versions.

Related errors


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