BerriAI/litellm · error · Exception

Failed to fetch file

Error message

Failed to fetch file '{file_path}': {e}

What it means

get_file_content wraps any HTTP status other than 401/403/404 into this generic Exception together with the underlying error text. Typical causes are 429 rate limiting (BitBucket Cloud throttles unauthenticated-heavy or bursty traffic), 5xx outages, and 400-class responses from a malformed branch or path. The status code itself is only visible inside the appended {e} text.

Solutions

  1. Inspect the appended error text for the status code: 429 -> back off (honor Retry-After header) and reduce concurrency/enable caching
  2. 5xx -> check status.bitbucket.org and retry with exponential backoff
  3. 400-ish -> verify branch name and path, and re-run _sanitize_file_path rules mentally (no '#', '?', '..')
  4. Cache fetched prompts so transient failures do not cascade at startup

Example fix

// before
content = client.get_file_content(path)  # burst of these -> 429 wrapped in 295
// after
import time
for attempt in range(5):
    try:
        content = client.get_file_content(path)
        break
    except Exception as e:
        if "429" in str(e) and attempt < 4:
            time.sleep(2 ** attempt)
            continue
        raise
Defensive patterns

Strategy: retry

Try / catch

import random, time

for attempt in range(5):
    try:
        content = client.get_file_content(path)
        break
    except Exception as e:
        msg = str(e)
        transient = ("429" in msg) or ("5" in msg.split(" ")[-1][:1] and "Failed to fetch" in msg)
        if "Failed to fetch file" in msg and transient and attempt < 4:
            time.sleep((2 ** attempt) + random.random())
            continue
        raise

Prevention

When it happens

Trigger: Burst-fetching many .prompt files at startup tripping the rate limit; BitBucket Cloud incident returning 5xx; a branch name with characters that break the URL; paginated endpoints mid-outage.

Common situations: Fan-out prompt loading in CI where dozens of clients start simultaneously; retry storms amplifying a transient 502; branch renamed after config was written.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at litellm/integrations/bitbucket/bitbucket_client.py:116

                # For binary files or when content-type is not text, try to decode as base64
                try:
                    return base64.b64decode(response.content).decode("utf-8")
                except Exception:
                    return response.text

        except Exception as e:
            # Check if it's an HTTP error
            if hasattr(e, "response") and hasattr(e.response, "status_code"):
                if e.response.status_code == 404:
                    return None
                elif e.response.status_code == 403:
                    raise Exception(
                        f"Access denied to file '{file_path}'. Check your BitBucket permissions for workspace '{self.workspace}' and repository '{self.repository}'."
                    )
                elif e.response.status_code == 401:
                    raise Exception("Authentication failed. Check your BitBucket access token and permissions.")
                else:
                    raise Exception(f"Failed to fetch file '{file_path}': {e}")
            else:
                raise Exception(f"Error fetching file '{file_path}': {e}")

    def list_files(self, directory_path: str = "", file_extension: str = ".prompt") -> list[str]:
        """
        List files in a directory with a specific extension.

        Args:
            directory_path: Directory path in the repository (empty for root)
            file_extension: File extension to filter by (default: .prompt)

        Returns:
            List of file paths
        """
        safe_dir: Final = _sanitize_file_path(directory_path) if directory_path else ""
        url: Final = f"{self.base_url}/repositories/{self.workspace}/{self.repository}/src/{self.branch}/{safe_dir}"

        try:

View on GitHub (pinned to 77b7c6c40c)