BerriAI/litellm · error · Exception

Failed to retrieve file

Error message

Failed to retrieve file {file_id} from provider: {str(e)}

What it means

Case 3 provider fallback: the hook takes the first (model_id -> provider_file_id) mapping, pulls that deployment's credentials via llm_router.get_deployment_credentials_with_provider, and calls litellm.afile_retrieve. Any provider-side failure is re-raised with the unified file id and the original cause chained via `from e`, so the real reason is inside the wrapped exception.

Solutions

  1. Read the text after 'from provider:' — it names the actual provider failure; fix that first
  2. Re-upload via POST /v1/files if the provider copy expired or was deleted
  3. Verify the mapped deployment's credentials (api key, AWS role, Vertex project/region) with a direct test call
  4. Retry with backoff for transient 5xx/network failures
Defensive patterns

Strategy: retry

Try / catch

try:
    f = await proxy.files.retrieve(file_id)
except Exception as e:
    msg = str(e)
    if "from provider" in msg and any(t in msg for t in ("429", "500", "502", "503", "timeout")):
        await asyncio.sleep(backoff())  # transient -> retry
    elif "401" in msg or "403" in msg:
        fix_credentials()             # not retryable
    else:
        reupload()                    # expired/deleted provider copy

Prevention

When it happens

Trigger: Provider-side copy of the file was deleted or expired (OpenAI files expire after about an hour by default); invalid or rotated credentials on the first mapped deployment; provider 5xx or network error during afile_retrieve.

Common situations: Retrieving a file long after upload past provider retention; API key rotation not yet reflected in the proxy's model_list; Bedrock/Vertex credentials scoped to the wrong bucket, role, or region.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/f20af79879719c85. Report an issue: GitHub.

Appendix: source

Thrown at enterprise/litellm_enterprise/proxy/hooks/managed_files.py:1364

            response = stored_file_object.file_object.model_copy(update={"id": file_id})
            return response

        # Case 3: Managed file exists in the database but not the file object (for. e.g the batch task might not have run)
        # So we fetch the file object from the provider. We deliberately do not store the result to avoid interfering with batch cost tracking code.
        if not llm_router:
            raise Exception(
                f"LiteLLM Managed File object with id={file_id} has no file_object "
                f"and llm_router is required to fetch from provider"
            )

        try:
            model_id, model_file_id = next(iter(stored_file_object.model_mappings.items()))
            credentials = llm_router.get_deployment_credentials_with_provider(model_id) or {}
            response = await litellm.afile_retrieve(file_id=model_file_id, **credentials)
            response.id = file_id  # Replace with unified ID
            return response
        except Exception as e:
            raise Exception(f"Failed to retrieve file {file_id} from provider: {str(e)}") from e

    async def afile_list(
        self,
        purpose: Optional[OpenAIFilesPurpose],
        litellm_parent_otel_span: Optional[Span],
        **data: Dict,
    ) -> List[OpenAIFileObject]:
        """Handled in files_endpoints.py"""
        return []

    def _is_batch_polling_enabled(self) -> bool:
        """
        Check if batch cost tracking is actually enabled and running.
        Returns:
            bool: True if batch cost tracking is active, False otherwise
        """
        try:
            # Import here to avoid circular dependencies

View on GitHub (pinned to 77b7c6c40c)