PrefectHQ/fastmcp · error · ResourceError
Error listing directory {self.path}
Error message
Error listing directory {self.path} What it means
DirectoryResource.list_files() wraps any exception from the glob iteration (PermissionError, OSError during traversal, bad pattern, etc.) into a ResourceError with the message 'Error listing directory {path}' and chains the original exception. It is the catch-all for failures during the recursive/non-recursive glob and per-file is_file() checks.
Source
Thrown at fastmcp_slim/fastmcp/resources/types.py:173
"""Ensure path is absolute."""
if not path.is_absolute():
raise ValueError("Path must be absolute")
return path
async def list_files(self) -> list[Path]:
"""List files in the directory."""
if not await self._async_path.exists():
raise FileNotFoundError(f"Directory not found: {self.path}")
if not await self._async_path.is_dir():
raise NotADirectoryError(f"Not a directory: {self.path}")
pattern = self.pattern or "*"
glob_fn = self._async_path.rglob if self.recursive else self._async_path.glob
try:
return [Path(p) async for p in glob_fn(pattern) if await p.is_file()]
except Exception as e:
raise ResourceError(f"Error listing directory {self.path}") from e
@override
async def read(self) -> ResourceResult:
"""Read the directory listing."""
try:
files: list[Path] = await self.list_files()
file_list = [str(f.relative_to(self.path)) for f in files]
content = json.dumps({"files": file_list}, indent=2)
return ResourceResult(
contents=[ResourceContent(content=content, mime_type=self.mime_type)]
)
except Exception as e:
raise ResourceError(f"Error reading directory {self.path}") from e
View on GitHub (pinned to 1f02114297)
Solutions
- Inspect the chained cause (`raise ... from e`) — log or catch ResourceError and read `e.__cause__` to find the real error (usually PermissionError).
- Fix filesystem permissions (chmod/chown) so the server process can read the directory.
- Validate/simplify the `pattern` configured on the resource.
- Reduce scope (disable recursive, narrower pattern) if traversal is hitting limits.
Example fix
// before
files = await resource.read() # opaque ResourceError
// after
try:
files = await resource.read()
except ResourceError as e:
logging.error("listing failed: %r", e.__cause__) Defensive patterns
Strategy: try-catch
Validate before calling
import os
path = '/data/reports'
if not os.access(path, os.R_OK | os.X_OK):
raise PermissionError(f'Cannot read directory: {path}') Try / catch
try:
files = await resource.list_files()
except ResourceError as e:
cause = e.__cause__
logger.error('listing %s failed: %r', resource.path, cause) Prevention
- Grant the server process read/execute on listed directories.
- Test glob patterns interactively before configuring them.
- Avoid recursive listings over volatile trees being modified concurrently.
When it happens
Trigger: Call read()/list_files() on a DirectoryResource (types.py:173) when glob raises — e.g. the directory is unreadable due to permissions, a glob pattern is malformed, or an entry disappears mid-iteration (race with deletion).
Common situations: Running as a user without read/execute permission on the directory or subdirectories; running recursive listings over huge trees that hit OS limits; another process deleting files while the listing runs; invalid pattern strings for the glob backend.
Understand the failure class
Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.
Related errors
- Could not restrict access to CLI state
- Could not create the CLI state directory
- Could not read CLI state: {path.name}
- Error reading file {self.path}
- Directory not found: {self.path}
AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29).
Data as JSON: /api/errors/1cb06affdad32063.
Report an issue: GitHub.