{"record":{"id":"be35e62e7c6ab2fe","repo":"BerriAI/litellm","slug":"file-id-must-be-a-scheme-uri","errorCode":null,"errorMessage":"file_id must be a {scheme} URI","messagePattern":"file_id must be a (.+?) URI","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/cloud_storage_security.py","lineNumber":143,"sourceCode":"            value = cast(Mapping[str, Any], trusted_model_credentials).get(\"allow_legacy_cloud_file_ids\")\n\n    if isinstance(value, bool):\n        return value\n    if isinstance(value, str):\n        return value.strip().lower() in {\"1\", \"true\", \"yes\", \"on\"}\n    return False\n\n\ndef validate_managed_cloud_file_id(\n    file_id: str,\n    scheme: str,\n    configured_bucket_name: str,\n    allowed_object_prefixes: Sequence[str],\n    allow_legacy_cloud_file_ids: bool = False,\n) -> tuple[str, str]:\n    decoded_file_id: Final = unquote(file_id)\n    if not decoded_file_id.startswith(scheme):\n        raise ValueError(f\"file_id must be a {scheme} URI\")\n\n    full_path: Final = decoded_file_id[len(scheme) :]\n    if \"/\" not in full_path:\n        raise ValueError(\"file_id must include a cloud storage object name\")\n\n    bucket_name, object_name = full_path.split(\"/\", 1)\n    configured_bucket, configured_prefix = split_configured_cloud_bucket_name(configured_bucket_name)\n    if bucket_name != configured_bucket:\n        raise ValueError(\"file_id bucket does not match the configured storage bucket\")\n\n    _validate_cloud_object_path(object_name)\n    allowed_prefixes = tuple(allowed_object_prefixes)\n    if configured_prefix:\n        allowed_prefixes = tuple(f\"{configured_prefix.rstrip('/')}/{prefix}\" for prefix in allowed_prefixes)\n\n    if object_name.startswith(allowed_prefixes):\n        return bucket_name, object_name\n","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/litellm_core_utils/cloud_storage_security.py#L125-L161","documentation":"validate_managed_cloud_file_id raises this when the URL-decoded file_id does not start with the expected scheme (e.g. 'gs://'). LiteLLM-managed file references are URIs of the form '<scheme><bucket>/<object>'; anything else — a bare filename or another provider's id — is rejected before any storage access, as a security check that only managed objects are fetched.","triggerScenarios":"Passing 'file-abc123' (an OpenAI-style file id) or 'reports/q3.csv' where the API expects 'gs://my-bucket/...'; also passing an Azure 'https://...' URL when the deployment is configured for GCS (scheme mismatch). The decoded string simply fails decoded_file_id.startswith(scheme).","commonSituations":"Migrating code from direct OpenAI files API to litellm managed files without rewriting stored file ids; storing provider-native ids in your DB and replaying them to litellm endpoints; percent-encoding that decodes to a scheme-less value.","solutions":["Prefix the reference with the correct scheme and managed path: 'gs://<configured-bucket>/<object-under-allowed-prefix>'.","If you have a raw provider file id, first upload/register the file through litellm's file management so you get back a managed URI, then use that.","Double-check you are calling the endpoint matching your configured backend (GCS vs Azure) so the scheme lines up."],"exampleFix":"# before\nfile_id = \"file-abc123\"           # provider-native id -> raises\n\n# after\nfile_id = \"gs://my-bucket/litellm/abc123.json\"  # managed <scheme>bucket/object URI","handlingStrategy":"type-guard","validationCode":"def is_managed_file_id(file_id: str, scheme: str = \"gs://\") -> bool:\n    from urllib.parse import unquote\n    return unquote(file_id).startswith(scheme)","typeGuard":"from urllib.parse import unquote\n\ndef is_managed_file_id(file_id: object, scheme: str = \"gs://\") -> bool:\n    \"\"\"Narrow to litellm-managed cloud URIs like gs://bucket/object.\"\"\"\n    if not isinstance(file_id, str):\n        return False\n    d = unquote(file_id)\n    return d.startswith(scheme) and \"/\" in d[len(scheme):]","tryCatchPattern":"from litellm.litellm_core_utils.cloud_storage_security import validate_managed_cloud_file_id\ntry:\n    bucket, obj = validate_managed_cloud_file_id(fid, \"gs://\", cfg_bucket, allowed_prefixes)\nexcept ValueError as e:\n    return HTTP 400 to the caller with the validator's message — do not retry","preventionTips":["Persist the managed URI returned by litellm file upload; never store provider-native ids for replay.","Centralize file_id construction in one helper that always emits scheme+bucket+object.","Reject scheme-less ids at your API boundary before they reach litellm."],"tags":["file-upload","cloud-storage","file-id","validation","security"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}