{"record":{"id":"b1de80c3c88a7cd3","repo":"BerriAI/litellm","slug":"access-denied-to-file-file-path-check-your-bi","errorCode":null,"errorMessage":"Access denied to file '{file_path}'. Check your BitBucket permissions for workspace '{self.workspace}' and repository '{self.repository}'.","messagePattern":"Access denied to file '(.+?)'\\. Check your BitBucket permissions for workspace '(.+?)' and repository '(.+?)'\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/integrations/bitbucket/bitbucket_client.py","lineNumber":110,"sourceCode":"            response.raise_for_status()\n\n            # BitBucket returns file content as base64 encoded\n            if response.headers.get(\"content-type\", \"\").startswith(\"text/\"):\n                return response.text\n            else:\n                # For binary files or when content-type is not text, try to decode as base64\n                try:\n                    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:","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/integrations/bitbucket/bitbucket_client.py#L92-L128","documentation":"Raised by BitBucketClient.get_file when the BitBucket API responds 403 to the raw-file fetch. The client's except block inspects the exception for a .response.status_code; 403 means authentication succeeded but the principal lacks read permission on that file/repo. 404 is deliberately mapped to None (file-not-found), so a 403 genuinely means access denial.","triggerScenarios":"App password/token scoped to a workspace the repository does not belong to; token without 'repository read' scope; repository or workspace name typo that resolves to a repo you cannot see; branch not accessible with the token's permissions.","commonSituations":"App password created with only account scopes and no repository scopes; workspace-repo mismatch (right repo name in the wrong workspace); recently rotated token with narrower scopes; team-based access control restricting the directory.","solutions":["Verify workspace and repository values resolve to the intended repo (open https://bitbucket.org/<workspace>/<repository>)","Recreate the app password / token with the repository:read scope (or full public/private repo read for private repos)","Confirm the account can view the file in the BitBucket UI while logged in as the token owner","Check that the branch configured exists and is readable (default is 'main')"],"exampleFix":"# before\nconfig = {\"workspace\": \"my-workspace\", \"repository\": \"my-repo\", \"access_token\": account_only_token}\n\n# after\n# app password with Repository access: Read enabled\nconfig = {\"workspace\": \"my-workspace\", \"repository\": \"my-repo\", \"access_token\": repo_read_token}","handlingStrategy":"try-catch","validationCode":"import httpx\n\ndef can_read_file(workspace: str, repo: str, path: str, token: str, branch: str = \"main\") -> bool:\n    url = f\"https://api.bitbucket.org/2.0/repositories/{workspace}/{repo}/src/{branch}/{path}\"\n    r = httpx.get(url, auth=(\"x-token-auth\", token), timeout=10)\n    return r.status_code == 200  # 403 = no permission, 404 = missing","typeGuard":null,"tryCatchPattern":"try:\n    content = client.get_file(path)\nexcept Exception as e:\n    msg = str(e)\n    if \"Access denied\" in msg:\n        raise PermissionError(f\"token lacks read access to {path}; check repo scopes\") from e\n    raise","preventionTips":["Create app passwords with Repository access: Read scope, minimum","Verify token permissions with a direct API call during setup, not at request time","Double-check workspace/repo spelling — the wrong combo can look like a permission error","Keep branch name correct (default 'main'; repos using 'master' need branch='master')"],"tags":["bitbucket","http-403","permissions","authentication"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}