{"record":{"id":"cc4731c261e79254","repo":"BerriAI/litellm","slug":"error-fetching-file-file-path-e","errorCode":null,"errorMessage":"Error fetching file '{file_path}': {e}","messagePattern":"Error fetching file '(.+?)': (.+?)","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/integrations/bitbucket/bitbucket_client.py","lineNumber":118,"sourceCode":"                    return base64.b64decode(response.content).decode(\"utf-8\")\n                except Exception:\n                    return response.text\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                elif e.response.status_code == 403:\n                    raise Exception(\n                        f\"Access denied to file '{file_path}'. Check your BitBucket permissions for workspace '{self.workspace}' and repository '{self.repository}'.\"\n                    )\n                elif e.response.status_code == 401:\n                    raise Exception(\"Authentication failed. Check your BitBucket access token and permissions.\")\n                else:\n                    raise Exception(f\"Failed to fetch file '{file_path}': {e}\")\n            else:\n                raise Exception(f\"Error fetching file '{file_path}': {e}\")\n\n    def list_files(self, directory_path: str = \"\", file_extension: str = \".prompt\") -> list[str]:\n        \"\"\"\n        List files in a directory with a specific extension.\n\n        Args:\n            directory_path: Directory path in the repository (empty for root)\n            file_extension: File extension to filter by (default: .prompt)\n\n        Returns:\n            List of file paths\n        \"\"\"\n        safe_dir: Final = _sanitize_file_path(directory_path) if directory_path else \"\"\n        url: Final = f\"{self.base_url}/repositories/{self.workspace}/{self.repository}/src/{self.branch}/{safe_dir}\"\n\n        try:\n            response: Final = self.http_handler.get(url, headers=self.headers)\n            response.raise_for_status()","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/integrations/bitbucket/bitbucket_client.py#L100-L136","documentation":"get_file_content wraps any exception that has no HTTP response attached — i.e., a transport-level failure: DNS resolution failure, connection refused/reset, TLS certificate verification error, proxy failures, or an unexpected decoding bug. The original exception text is appended verbatim, which distinguishes it from the HTTP-status variants (293-295).","triggerScenarios":"K8s pod without egress to api.bitbucket.org (network policy/air-gapped cluster); corporate proxy required but HTTP_PROXY/HTTPS_PROXY unset; TLS-intercepting middlebox with an untrusted CA making verification fail; self-hosted base_url unreachable; IPv6/DNS misconfiguration.","commonSituations":"Services moved into a restricted network segment; certificates rotated on the interception proxy; CI runners behind NAT with flaky DNS; local dev on VPN split-tunnel that drops the API host.","solutions":["Verify basic reachability: curl https://api.bitbucket.org/2.0 from the same container/host","Configure the proxy via HTTPS_PROXY/HTTP_PROXY (and NO_PROXY for internal hosts) in the process env","For TLS interception, trust the CA bundle: mount the corp CA and set SSL_CERT_FILE / REQUESTS_CA_BUNDLE for the httpx handler","Pin a stable DNS/resolver in the pod spec (dnsPolicy) if resolution is flaky"],"exampleFix":"// before: pod has no egress -> 'Error fetching file ... [Errno -2] Name or service not known'\n// after\nexport HTTPS_PROXY=\"http://proxy.corp.internal:3128\"\nexport SSL_CERT_FILE=\"/etc/ssl/certs/corp-ca-bundle.crt\"\npython -m myapp  # BitBucketClient now reaches api.bitbucket.org","handlingStrategy":"retry","validationCode":"import socket, urllib.request\n\nhost = \"api.bitbucket.org\"\ntry:\n    socket.getaddrinfo(host, 443)\nexcept socket.gaierror:\n    raise RuntimeError(f\"cannot resolve {host}; fix DNS/egress before using BitBucketClient\")\n# optional reachability probe\ntry:\n    urllib.request.urlopen(f\"https://{host}/2.0\", timeout=5)\nexcept Exception as e:\n    raise RuntimeError(f\"no route to {host}: {e}\")","typeGuard":null,"tryCatchPattern":"import random, time\n\nfor attempt in range(3):\n    try:\n        content = client.get_file_content(path)\n        break\n    except Exception as e:\n        if \"Error fetching file\" in str(e) and attempt < 2:  # transport-level only\n            time.sleep(2 ** attempt + random.random())\n            continue\n        raise","preventionTips":["Verify egress/DNS from the exact container the client runs in (curl the API)","Configure HTTPS_PROXY/HTTP_PROXY where corporate proxies are mandatory","Trust interception CAs via SSL_CERT_FILE/REQUESTS_CA_BUNDLE for httpx","Distinguish by prefix: 'Error fetching file' = transport; 'Failed to fetch file' = HTTP status"],"tags":["bitbucket","network","dns","proxy","tls","connection"],"backgroundTag":"network-request-failed","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}