{"record":{"id":"1cb06affdad32063","repo":"PrefectHQ/fastmcp","slug":"error-listing-directory-self-path","errorCode":null,"errorMessage":"Error listing directory {self.path}","messagePattern":"Error listing directory (.+?)","errorType":"exception","errorClass":"ResourceError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/resources/types.py","lineNumber":173,"sourceCode":"        \"\"\"Ensure path is absolute.\"\"\"\n        if not path.is_absolute():\n            raise ValueError(\"Path must be absolute\")\n        return path\n\n    async def list_files(self) -> list[Path]:\n        \"\"\"List files in the directory.\"\"\"\n        if not await self._async_path.exists():\n            raise FileNotFoundError(f\"Directory not found: {self.path}\")\n        if not await self._async_path.is_dir():\n            raise NotADirectoryError(f\"Not a directory: {self.path}\")\n\n        pattern = self.pattern or \"*\"\n\n        glob_fn = self._async_path.rglob if self.recursive else self._async_path.glob\n        try:\n            return [Path(p) async for p in glob_fn(pattern) if await p.is_file()]\n        except Exception as e:\n            raise ResourceError(f\"Error listing directory {self.path}\") from e\n\n    @override\n    async def read(self) -> ResourceResult:\n        \"\"\"Read the directory listing.\"\"\"\n        try:\n            files: list[Path] = await self.list_files()\n\n            file_list = [str(f.relative_to(self.path)) for f in files]\n\n            content = json.dumps({\"files\": file_list}, indent=2)\n            return ResourceResult(\n                contents=[ResourceContent(content=content, mime_type=self.mime_type)]\n            )\n        except Exception as e:\n            raise ResourceError(f\"Error reading directory {self.path}\") from e\n","sourceCodeStart":155,"sourceCodeEnd":189,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/resources/types.py#L155-L189","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nfiles = await resource.read()  # opaque ResourceError\n\n// after\ntry:\n    files = await resource.read()\nexcept ResourceError as e:\n    logging.error(\"listing failed: %r\", e.__cause__)","handlingStrategy":"try-catch","validationCode":"import os\npath = '/data/reports'\nif not os.access(path, os.R_OK | os.X_OK):\n    raise PermissionError(f'Cannot read directory: {path}')","typeGuard":null,"tryCatchPattern":"try:\n    files = await resource.list_files()\nexcept ResourceError as e:\n    cause = e.__cause__\n    logger.error('listing %s failed: %r', resource.path, cause)","preventionTips":["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."],"tags":["filesystem","permissions","resources","glob"],"backgroundTag":"permission-denied","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}