BerriAI/litellm · error · Exception

Failed to get file metadata for

Error message

Failed to get file metadata for '{file_path}': {e}

What it means

Raised by BitBucketClient.get_file_metadata when the ranged GET for a file (Range: bytes=0-0) fails with an HTTP status error other than 404 — 404 is converted to a None return. So this fires on 401 (authentication failed), 403 (token lacks read scope for the path), 429 (rate limit), and 5xx responses from the BitBucket API.

Solutions

  1. Remember None means 'not found' — only non-404 failures raise, so treat this as an auth/capacity problem
  2. Verify the token still authenticates: curl -H "Authorization: Bearer $TOKEN" "https://api.bitbucket.org/2.0/user"
  3. Confirm the token has repository read scope for workspace/repository
  4. Retry with exponential backoff for 429/5xx wrapped causes
Defensive patterns

Strategy: try-catch

Validate before calling

# None return is the built-in 404 path; pre-check relevance of the token instead
import httpx, os

def token_valid() -> bool:
    try:
        r = httpx.get("https://api.bitbucket.org/2.0/user",
                      headers={"Authorization": f"Bearer {os.getenv('BITBUCKET_ACCESS_TOKEN','')}"},
                      timeout=5)
        return r.status_code == 200
    except httpx.RequestError:
        return False

Try / catch

try:
    meta = client.get_file_metadata(path)
except Exception as e:
    if "401" in str(e) or "Authentication" in str(e):
        ...  # refresh token
    else:
        ...  # rate limit / 5xx: retry with backoff
else:
    if meta is None:
        ...  # file genuinely absent (404 path)

Prevention

When it happens

Trigger: Calling get_file_metadata for a file in a repo the token cannot read (403), with an expired access token (401), during BitBucket API rate limiting (429), or during a BitBucket-side incident (5xx). The path has already passed _sanitize_file_path, so traversal/URL-special-character mistakes raise ValueError earlier.

Common situations: Pre-checking that a .prompt file exists before loading it; tokens with only write-but-not-read scopes; heavy polling loops hitting rate limits; tokens revoked mid-session.

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/44d8ed53cd779346. Report an issue: GitHub.

Appendix: source

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

        try:
            # Use GET with Range header to get just the headers (HEAD equivalent)
            headers: Final = self.headers.copy()
            headers["Range"] = "bytes=0-0"  # Request only first byte to get headers

            response: Final = self.http_handler.get(url, headers=headers)
            response.raise_for_status()

            return {
                "content_type": response.headers.get("content-type"),
                "content_length": response.headers.get("content-length"),
                "last_modified": response.headers.get("last-modified"),
            }
        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
                raise Exception(f"Failed to get file metadata for '{file_path}': {e}")
            else:
                raise Exception(f"Error getting file metadata for '{file_path}': {e}")

    def close(self):
        """Close the HTTP handler to free resources."""
        if hasattr(self, "http_handler"):
            self.http_handler.close()

View on GitHub (pinned to 77b7c6c40c)