{"record":{"id":"f3401b77e4852465","repo":"PrefectHQ/fastmcp","slug":"error-reading-file-self-path","errorCode":null,"errorMessage":"Error reading file {self.path}","messagePattern":"Error reading file (.+?)","errorType":"exception","errorClass":"ResourceError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/resources/types.py","lineNumber":110,"sourceCode":"        \"\"\"Set is_binary based on mime_type if not explicitly set.\"\"\"\n        if is_binary:\n            return True\n        mime_type = info.data.get(\"mime_type\", \"text/plain\")\n        return not mime_type.startswith(\"text/\")\n\n    @override\n    async def read(self) -> ResourceResult:\n        \"\"\"Read the file content.\"\"\"\n        try:\n            if self.is_binary:\n                content: str | bytes = await self._async_path.read_bytes()\n            else:\n                content = await self._async_path.read_text(encoding=self.encoding)\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 file {self.path}\") from e\n\n\nclass HttpResource(Resource):\n    \"\"\"A resource that reads from an HTTP endpoint.\"\"\"\n\n    url: str = Field(description=\"URL to fetch content from\")\n    mime_type: str = Field(\n        default=\"application/json\", description=\"MIME type of the resource content\"\n    )\n\n    @override\n    async def read(self) -> ResourceResult:\n        \"\"\"Read the HTTP content.\"\"\"\n        async with httpx2.AsyncClient() as client:\n            response = await client.get(self.url)\n            _ = response.raise_for_status()\n            return ResourceResult(\n                contents=[","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/resources/types.py#L92-L128","documentation":"When FileResource.read() fails for any reason (file missing, permission denied, decode error, etc.), the original exception is wrapped in a ResourceError whose message names the path. The underlying cause is chained (raise ... from e), so inspect __cause__ to see the real OS-level error.","triggerScenarios":"Calling read() (directly or via MCP resource read) on a FileResource whose path doesn't exist, isn't readable, was deleted after registration, or whose bytes don't decode with the configured encoding.","commonSituations":"File removed/moved after server start; running server as a user lacking read permission; encoding mismatch (binary file read as UTF-8 text); wrong is_binary flag for the content type.","solutions":["Check the chained cause (e.g. try/except ResourceError as e: print(e.__cause__)) to see the OS error and fix it - create the file or fix permissions","Set is_binary=True and an appropriate binary mime_type for non-text files","Verify the path exists and is readable at startup: Path(path).exists() and os.access(path, os.R_OK)","Wrap reads in try/except ResourceError and return a helpful message to the client"],"exampleFix":"// before\ncontent = await file_resource.read()  # ResourceError: Error reading file /data/x.csv\n// after\ntry:\n    result = await file_resource.read()\nexcept ResourceError as e:\n    logger.error(f\"resource read failed: {e} (cause: {e.__cause__})\")\n    raise","handlingStrategy":"try-catch","validationCode":"import os\nfrom pathlib import Path\ndef assert_readable(p):\n    path = Path(p)\n    if not path.exists():\n        raise FileNotFoundError(path)\n    if not os.access(path, os.R_OK):\n        raise PermissionError(path)","typeGuard":"def file_readable(p) -> bool:\n    import os\n    path = Path(p)\n    return path.is_file() and os.access(path, os.R_OK)","tryCatchPattern":"try:\n    result = await file_resource.read()\nexcept ResourceError as e:\n    logger.error(\"read failed for %s: %s\", file_resource.path, e.__cause__)\n    raise","preventionTips":["Check existence/readability at startup or first access, not only at read time","Set is_binary=True and a binary mime_type for non-UTF-8 files","Log e.__cause__ - the wrapped OS error is what matters for diagnosis","Re-register resources if the underlying files move"],"tags":["filesystem","io","resources"],"backgroundTag":"file-read-failed","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}