PrefectHQ/fastmcp · error · ValueError

Path must be absolute

Error message

Path must be absolute

What it means

FileResource wraps a local file path, which is stored as a pathlib.Path and must be absolute so the resource resolves identically regardless of the server's current working directory. Pydantic's field validator rejects relative paths (e.g. "data/file.txt" or "./notes.md") at construction time.

Source

Thrown at fastmcp_slim/fastmcp/resources/types.py:86

    encoding: str | None = Field(
        default="utf-8",
        description=(
            "Encoding to use when reading text files. "
            "Defaults to 'utf-8' for cross-platform compatibility. "
            "Set to None to use the system default encoding."
        ),
    )

    @property
    def _async_path(self) -> AsyncPath:
        return AsyncPath(self.path)

    @pydantic.field_validator("path")
    @classmethod
    def validate_absolute_path(cls, path: Path) -> Path:
        """Ensure path is absolute."""
        if not path.is_absolute():
            raise ValueError("Path must be absolute")
        return path

    @pydantic.field_validator("is_binary")
    @classmethod
    def set_binary_from_mime_type(cls, is_binary: bool, info: ValidationInfo) -> bool:
        """Set is_binary based on mime_type if not explicitly set."""
        if is_binary:
            return True
        mime_type = info.data.get("mime_type", "text/plain")
        return not mime_type.startswith("text/")

    @override
    async def read(self) -> ResourceResult:
        """Read the file content."""
        try:
            if self.is_binary:
                content: str | bytes = await self._async_path.read_bytes()
            else:

View on GitHub (pinned to 1f02114297)

Solutions

  1. Convert to absolute: Path("data/file.txt").resolve() or Path(__file__).parent / "data/file.txt"
  2. Resolve from a configured base directory: BASE_DIR / rel_path
  3. Have users provide absolute paths in configuration and validate early

Example fix

// before
FileResource(uri="file:///data.txt", path=Path("data/data.txt"))
// after
FileResource(uri="file:///data/data.txt", path=Path("/var/app/data/data.txt"))
// or
path = (BASE_DIR / "data/data.txt").resolve()
Defensive patterns

Strategy: validation

Validate before calling

from pathlib import Path
def resolve_file_path(p) -> Path:
    path = Path(p)
    if not path.is_absolute():
        path = (BASE_DIR / path).resolve()
    return path

Type guard

def is_absolute_path(p) -> bool:
    return Path(p).is_absolute()

Try / catch

from pydantic import ValidationError
try:
    res = FileResource(uri=uri, path=Path(p))
except ValidationError as e:
    if "Path must be absolute" in str(e):
        res = FileResource(uri=uri, path=Path(p).resolve())
    else:
        raise

Prevention

When it happens

Trigger: Constructing FileResource(uri=..., path=Path("relative/file.txt"), ...) or via Resource.from_file with a relative path string.

Common situations: Hardcoded relative paths in config; paths built from CWD assumptions in dev scripts; container working directories differing from the host; user-supplied config paths that are relative.

Related errors


AI-assisted analysis of PrefectHQ/fastmcp@1f02114297 (2026-08-29). Data as JSON: /api/errors/c3d9baf0e23b3ddd. Report an issue: GitHub.