BerriAI/litellm · error · Exception
Failed to list files in
Error message
Failed to list files in '{directory_path}': {e} What it means
Catch-all wrapping any non-401/403/404 failure of the tree request in list_files, with the original exception included. Covers transport errors (DNS, refused connections, TLS), GitLab 5xx, rate limiting (429), and timeouts. A 404 would silently return [], so reaching this message means a genuine infrastructure or configuration problem, not a missing directory.
Solutions
- Confirm the GitLab host is up and base_url includes /api/v4
- Add backoff/jitter and cache directory listings between runs
- Retry transient 5xx/429 responses
- Reduce scope: pass a narrower directory_path instead of listing recursively from the root
Example fix
# before: recursive listing of the whole repo on every boot
files = client.list_files(recursive=True)
# after: scope the listing to the prompts directory
files = client.list_files("prompts", recursive=True) Defensive patterns
Strategy: retry
Validate before calling
import httpx
def can_list_now(client) -> bool:
"""Cheap readiness check for the tree API before a big listing."""
try:
client.list_files("") # single page, root only
return True
except Exception:
return False Try / catch
import time
def list_with_retry(client, path, attempts=3):
for i in range(attempts):
try:
return client.list_files(path)
except Exception as e:
msg = str(e)
retryable = "Failed to list files" in msg and any(
t in msg for t in ("timed out", "ConnectError", "500", "502", "503", "429")
)
if i == attempts - 1 or not retryable:
raise
time.sleep(2 ** i) Prevention
- Cache the prompt file listing; refresh on a schedule, not per request
- Rate-limit discovery loops to stay under GitLab's limits
- Scope listings to the prompts directory to keep responses small
When it happens
Trigger: Self-hosted GitLab unreachable or restarting; 429 rate limiting from aggressive polling; 5xx during GitLab incidents; TLS/proxy failures; timeouts enumerating very large trees (no pagination parameters are sent).
Common situations: Startup prompt discovery hitting a sleeping on-prem instance; CI jobs hammering the tree API; GitLab.com degradation; huge repositories with thousands of entries.
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
- Failed to fetch file
- Failed to fetch file
- Failed to get repository info
- Access denied to directory
- Error listing files in
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/cfaebbc4d6dc32d9.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/integrations/gitlab/gitlab_client.py:230
files: Final[list[str]] = []
for item in data:
if item.get("type") == "blob":
file_path = item.get("path", "")
if not file_extension or file_path.endswith(file_extension):
files.append(file_path)
return files
except Exception as e:
status: Final = getattr(getattr(e, "response", None), "status_code", None)
if status == 404:
return []
if status == 403:
raise Exception(
f"Access denied to directory '{directory_path}'. Check your GitLab permissions for project '{self.project}'."
)
if status == 401:
raise Exception("Authentication failed. Check your GitLab token and auth_method.")
raise Exception(f"Failed to list files in '{directory_path}': {e}")
def get_repository_info(self) -> dict[str, Any]:
"""Get information about the project/repository."""
url: Final = f"{self.base_url}/projects/{self._project_enc}"
try:
resp: Final = self.http_handler.get(url, headers=self.headers)
resp.raise_for_status()
return resp.json()
except Exception as e:
raise Exception(f"Failed to get repository info: {e}")
def test_connection(self) -> bool:
"""Test the connection to the GitLab project."""
try:
self.get_repository_info()
return True
except Exception:
return FalseView on GitHub (pinned to 77b7c6c40c)