BerriAI/litellm · error · Exception

Access denied to directory '{directory_path}'. Check your Bi

Error message

Access denied to directory '{directory_path}'. Check your BitBucket permissions for workspace '{self.workspace}' and repository '{self.repository}'.

What it means

Raised by BitBucketClient.list_files when the BitBucket API responds 403 while enumerating a directory. Mirrors get_file's 403 handling but for the directory listing endpoint: credentials authenticated, yet the token/account cannot read that directory in the workspace/repository. 404 maps to [] (empty list), so only permission problems raise here.

Source

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

            data: Final = response.json()
            files: Final = []

            for item in data.get("values", []):
                if item.get("type") == "commit_file":
                    file_path = item.get("path", "")
                    if file_path.endswith(file_extension):
                        files.append(file_path)

            return files

        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 []
                elif e.response.status_code == 403:
                    raise Exception(
                        f"Access denied to directory '{directory_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 list files in '{directory_path}': {e}")
            else:
                raise Exception(f"Error listing files in '{directory_path}': {e}")

    def get_repository_info(self) -> dict[str, Any]:
        """
        Get information about the repository.

        Returns:
            Dictionary containing repository information
        """
        url: Final = f"{self.base_url}/repositories/{self.workspace}/{self.repository}"

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Grant the credential's account read access to the repository (or recreate the app password with repository:read scope)
  2. Confirm workspace/repository spellings and that the directory exists in that repo
  3. Test access in the UI as the token owner, or curl https://api.bitbucket.org/2.0/repositories/<ws>/<repo>/src/<branch>/<dir> with the token
  4. Narrow directory_path to a directory you know is readable

Example fix

# before
token = account_scoped_app_password  # no repo scope
client.list_files("prompts")  # 403 -> Exception

# after
# app password with Repository access: Read
token = repo_read_app_password
client.list_files("prompts")
Defensive patterns

Strategy: try-catch

Validate before calling

import httpx

def can_list_directory(workspace: str, repo: str, directory: str, token: str, branch: str = "main") -> bool:
    url = f"https://api.bitbucket.org/2.0/repositories/{workspace}/{repo}/src/{branch}/{directory}"
    r = httpx.get(url, auth=("x-token-auth", token), timeout=10)
    return r.status_code == 200

Try / catch

try:
    files = client.list_files(directory_path)
except Exception as e:
    if "Access denied to directory" in str(e):
        raise PermissionError(f"token cannot list {directory_path}; grant repository read scope") from e
    raise

Prevention

When it happens

Trigger: Calling list_files(directory_path=...) on a directory the token cannot read; app password without repository read scope; workspace/repo values pointing at a private repo the credential owner is not a member of; branch inaccessible.

Common situations: Token scoped to a different repository than the one configured; directory inside a submodule or restricted folder; team permission changes after the integration was set up; scanning the repo root when the token only covers specific paths.

Understand the failure class

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/f47200b532b56190. Report an issue: GitHub.