BerriAI/litellm · error · ValueError

file_id must reference a LiteLLM-managed storage object

Error message

file_id must reference a LiteLLM-managed storage object

What it means

The final guard of validate_managed_cloud_file_id: the object name does not start with any allowed prefix (each optionally nested under the configured bucket prefix) and legacy ids are not permitted, so the URI — though structurally valid and in the right bucket — does not reference a LiteLLM-managed storage object. This is the core anti-confusion check stopping clients from making the proxy read arbitrary keys in the bucket.

Source

Thrown at litellm/litellm_core_utils/cloud_storage_security.py:167

    bucket_name, object_name = full_path.split("/", 1)
    configured_bucket, configured_prefix = split_configured_cloud_bucket_name(configured_bucket_name)
    if bucket_name != configured_bucket:
        raise ValueError("file_id bucket does not match the configured storage bucket")

    _validate_cloud_object_path(object_name)
    allowed_prefixes = tuple(allowed_object_prefixes)
    if configured_prefix:
        allowed_prefixes = tuple(f"{configured_prefix.rstrip('/')}/{prefix}" for prefix in allowed_prefixes)

    if object_name.startswith(allowed_prefixes):
        return bucket_name, object_name

    if allow_legacy_cloud_file_ids:
        if configured_prefix and not object_name.startswith(f"{configured_prefix.rstrip('/')}/"):
            raise ValueError("file_id object does not match the configured storage prefix")
        return bucket_name, object_name

    raise ValueError("file_id must reference a LiteLLM-managed storage object")

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Upload or register the file through litellm's managed file flow so it lands under an allowed prefix and returns a valid id.
  2. If the object is legitimate, add its folder to the deployment's allowed object prefixes (or move the object under an existing allowed prefix).
  3. As a migration measure only, enable allow_legacy_cloud_file_ids if your version exposes it — understanding this widens what the proxy will read.

Example fix

# before
file_id = "gs://my-bucket/random/key.json"    # outside allowed prefix 'litellm/'

# after
# register through litellm file management, then use the returned id:
file_id = "gs://my-bucket/litellm/managed-key.json"
Defensive patterns

Strategy: validation

Validate before calling

def under_allowed_prefixes(file_id: str, configured: str, allowed: tuple[str, ...], scheme: str = "gs://") -> bool:
    cfg_bucket, _, cfg_prefix = configured.strip().partition("/")
    bucket, obj = unquote(file_id)[len(scheme):].split("/", 1)
    prefixes = tuple(f"{cfg_prefix.rstrip('/')}/{p}" for p in allowed) if cfg_prefix else allowed
    return bucket == cfg_bucket and obj.startswith(prefixes)

Type guard

def is_managed_object_reference(v: object, configured: str, allowed: tuple[str, ...], scheme: str = "gs://") -> bool:
    if not isinstance(v, str):
        return False
    try:
        bucket, obj = unquote(v)[len(scheme):].split("/", 1)
    except ValueError:
        return False
    cfg_bucket, _, cfg_prefix = configured.strip().partition("/")
    prefixes = tuple(f"{cfg_prefix.rstrip('/')}/{p}" for p in allowed) if cfg_prefix else allowed
    return bucket == cfg_bucket and obj.startswith(prefixes)

Try / catch

try:
    validate_managed_cloud_file_id(fid, scheme, cfg, allowed_prefixes)
except ValueError as e:
    if "LiteLLM-managed" in str(e):
        return HTTP 403  # client tried to reference a non-managed key; never auto-widen prefixes

Prevention

When it happens

Trigger: file_id = 'gs://my-bucket/backups/db.dump' when the only allowed prefix is 'litellm/' (and allow_legacy_cloud_file_ids is False/default); passing hand-crafted URIs naming keys uploaded outside litellm's file management.

Common situations: Attempting to reuse objects uploaded directly via gsutil/console with litellm file endpoints; pentest/probing requests trying to read arbitrary keys; misconfigured allowed_object_prefixes that no longer matches where files are actually written.

Related errors


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