{"record":{"id":"44d8ed53cd779346","repo":"BerriAI/litellm","slug":"failed-to-get-file-metadata-for-file-path-e","errorCode":null,"errorMessage":"Failed to get file metadata for '{file_path}': {e}","messagePattern":"Failed to get file metadata for '(.+?)': (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/integrations/bitbucket/bitbucket_client.py","lineNumber":243,"sourceCode":"        try:\n            # Use GET with Range header to get just the headers (HEAD equivalent)\n            headers: Final = self.headers.copy()\n            headers[\"Range\"] = \"bytes=0-0\"  # Request only first byte to get headers\n\n            response: Final = self.http_handler.get(url, headers=headers)\n            response.raise_for_status()\n\n            return {\n                \"content_type\": response.headers.get(\"content-type\"),\n                \"content_length\": response.headers.get(\"content-length\"),\n                \"last_modified\": response.headers.get(\"last-modified\"),\n            }\n        except Exception as e:\n            # Check if it's an HTTP error\n            if hasattr(e, \"response\") and hasattr(e.response, \"status_code\"):\n                if e.response.status_code == 404:\n                    return None\n                raise Exception(f\"Failed to get file metadata for '{file_path}': {e}\")\n            else:\n                raise Exception(f\"Error getting file metadata for '{file_path}': {e}\")\n\n    def close(self):\n        \"\"\"Close the HTTP handler to free resources.\"\"\"\n        if hasattr(self, \"http_handler\"):\n            self.http_handler.close()\n","sourceCodeStart":225,"sourceCodeEnd":251,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/bitbucket/bitbucket_client.py#L225-L251","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Remember None means 'not found' — only non-404 failures raise, so treat this as an auth/capacity problem","Verify the token still authenticates: curl -H \"Authorization: Bearer $TOKEN\" \"https://api.bitbucket.org/2.0/user\"","Confirm the token has repository read scope for workspace/repository","Retry with exponential backoff for 429/5xx wrapped causes"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"# None return is the built-in 404 path; pre-check relevance of the token instead\nimport httpx, os\n\ndef token_valid() -> bool:\n    try:\n        r = httpx.get(\"https://api.bitbucket.org/2.0/user\",\n                      headers={\"Authorization\": f\"Bearer {os.getenv('BITBUCKET_ACCESS_TOKEN','')}\"},\n                      timeout=5)\n        return r.status_code == 200\n    except httpx.RequestError:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    meta = client.get_file_metadata(path)\nexcept Exception as e:\n    if \"401\" in str(e) or \"Authentication\" in str(e):\n        ...  # refresh token\n    else:\n        ...  # rate limit / 5xx: retry with backoff\nelse:\n    if meta is None:\n        ...  # file genuinely absent (404 path)","preventionTips":["Remember the contract: None means not-found; only non-404 failures raise","Keep the token's read scope aligned with the repos being polled","Rate-limit metadata polling loops to avoid 429s"],"tags":["bitbucket","http","file-metadata","authentication"],"backgroundTag":"http-request-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}