{"record":{"id":"53cd6bc58f9311c7","repo":"PrefectHQ/fastmcp","slug":"invalid-root-r","errorCode":null,"errorMessage":"Invalid root: {r}","messagePattern":"Invalid root: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"fastmcp_slim/fastmcp/client/roots.py","lineNumber":30,"sourceCode":"RootsList: TypeAlias = list[str] | list[mcp_types.Root] | list[str | mcp_types.Root]\n\nRootsHandler: TypeAlias = (\n    Callable[[RequestContext[ClientSession, LifespanContextT]], RootsList]\n    | Callable[[RequestContext[ClientSession, LifespanContextT]], Awaitable[RootsList]]\n)\n\n\ndef convert_roots_list(roots: RootsList) -> list[mcp_types.Root]:\n    roots_list = []\n    for r in roots:\n        if isinstance(r, mcp_types.Root):\n            roots_list.append(r)\n        elif isinstance(r, pydantic.FileUrl):\n            roots_list.append(mcp_types.Root(uri=r))\n        elif isinstance(r, str):\n            roots_list.append(mcp_types.Root(uri=pydantic.FileUrl(r)))\n        else:\n            raise ValueError(f\"Invalid root: {r}\")\n    return roots_list\n\n\ndef create_roots_callback(\n    handler: RootsList | RootsHandler,\n) -> ListRootsFnT:\n    if isinstance(handler, list):\n        return _create_roots_callback_from_roots(handler)\n    elif callable(handler):\n        return _create_roots_callback_from_fn(handler)\n    else:\n        raise ValueError(f\"Invalid roots handler: {handler}\")\n\n\ndef _create_roots_callback_from_roots(\n    roots: RootsList,\n) -> ListRootsFnT:\n    roots = convert_roots_list(roots)","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/PrefectHQ/fastmcp/blob/1f021142978e0861cd910c8df4e8074bc7cf3978/fastmcp_slim/fastmcp/client/roots.py#L12-L48","documentation":"ValueError from `convert_roots_list` when an item in a roots list is not one of the accepted root representations (mcp_types.Root, pydantic.FileUrl, or str). The library cannot coerce the value into an MCP Root.","triggerScenarios":"Passing a roots list to `client.set_roots(...)` (through `create_roots_callback` → `_create_roots_callback_from_roots`) containing e.g. a pathlib.Path, an `AnyUrl` that is not a FileUrl (http://...), an int, or None.","commonSituations":"Passing `pathlib.Path` objects from filesystem walking code; passing http(s) URLs instead of file:// URLs; passing directories from config that were never converted to strings.","solutions":["Convert values to `str` before passing (str(Path(...))) — strings are coerced via pydantic.FileUrl","Ensure strings are valid file:// URLs, e.g. `Path(p).absolute().as_uri()`","Wrap non-file URLs appropriately or drop them — roots must be file:// URIs","Use `mcp_types.Root(uri=pydantic.FileUrl(...))` explicitly for full control"],"exampleFix":"// before\nclient.set_roots([Path(\"/data\")])  # ValueError\n\n// after\nclient.set_roots([Path(\"/data\").absolute().as_uri()])","handlingStrategy":"validation","validationCode":"import pydantic\nfrom mcp import types as mcp_types\n\ndef valid_root(r) -> bool:\n    return (isinstance(r, mcp_types.Root)\n            or isinstance(r, pydantic.FileUrl)\n            or (isinstance(r, str) and _is_file_url(r)))\n\ndef _is_file_url(s: str) -> bool:\n    try:\n        pydantic.FileUrl(s); return True\n    except Exception:\n        return False","typeGuard":"def is_root(r) -> bool:\n    import pydantic\n    from mcp import types as mcp_types\n    if isinstance(r, mcp_types.Root) or isinstance(r, pydantic.FileUrl):\n        return True\n    if isinstance(r, str):\n        try:\n            pydantic.FileUrl(r); return True\n        except Exception:\n            return False\n    return False","tryCatchPattern":null,"preventionTips":["Always convert paths with Path(...).absolute().as_uri() before set_roots","Never pass pathlib.Path or http:// URLs as roots","Validate the whole list with is_root before calling set_roots","Only pass file:// URIs — roots are filesystem-scoped by spec"],"tags":["mcp","roots","validation","client"],"backgroundTag":"invalid-argument-type","analyzedSha":"1f021142978e0861cd910c8df4e8074bc7cf3978","analyzedAt":"2026-08-29T14:31:16.082Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}