pytest-dev/pytest · error · ValueError

can only pass None, Path instances or non-empty strings to L

Error message

can only pass None, Path instances or non-empty strings to LocalPath

What it means

LocalPath.__init__ converts its argument via os.fspath, which only accepts str, bytes, or os.PathLike objects. If fspath raises TypeError (the argument is an int, list, None-other, dict, arbitrary object), pytest re-raises it as ValueError with this message. LocalPath deliberately narrows the accepted types to path-like objects and the None sentinel (which means cwd).

Source

Thrown at src/_pytest/_py/path.py:291

    sep = os.sep

    def __init__(self, path=None, expanduser=False):
        """Initialize and return a local Path instance.

        Path can be relative to the current directory.
        If path is None it defaults to the current working directory.
        If expanduser is True, tilde-expansion is performed.
        Note that Path instances always carry an absolute path.
        Note also that passing in a local path object will simply return
        the exact same path object. Use new() to get a new copy.
        """
        if path is None:
            self.strpath = error.checked_call(os.getcwd)
        else:
            try:
                path = os.fspath(path)
            except TypeError:
                raise ValueError(
                    "can only pass None, Path instances "
                    "or non-empty strings to LocalPath"
                )
            if expanduser:
                path = os.path.expanduser(path)
            self.strpath = abspath(path)

    if sys.platform != "win32":

        def chown(self, user, group, rec=0):
            """Change ownership to the given user and group.
            user and group may be specified by a number or
            by a name.  if rec is True change ownership
            recursively.
            """
            uid = getuserid(user)
            gid = getgroupid(group)
            if rec:

View on GitHub (pinned to 0d6fbdeffa)

Solutions

  1. Pass a str or os.PathLike: `LocalPath('/tmp/x')` or `LocalPath(pathlib.Path('/tmp/x'))`.
  2. If you have components, join first: `LocalPath(os.path.join(*components))`.
  3. Implement os.fspath/__fspath__ on your wrapper class so it is path-like.

Example fix

# before
LocalPath(12345)
# after
LocalPath('/tmp/dir_12345')
Defensive patterns

Strategy: type-guard

Validate before calling

import os
def is_path_like(v) -> bool:
    return v is None or isinstance(v, (str, bytes, os.PathLike))
# usage
if not is_path_like(arg):
    raise TypeError('LocalPath requires str/bytes/os.PathLike or None')
LocalPath(arg)

Type guard

import os
def is_path_like_or_none(v) -> bool:
    return v is None or isinstance(v, (str, bytes, os.PathLike))

Prevention

When it happens

Trigger: Calling LocalPath(123), LocalPath([]), LocalPath(None, ...) is fine (None means cwd), LocalPath(SomeRandomObject()). Triggered at LocalPath.__init__ (src/_pytest/_py/path.py:288-294). Note: bytes paths ARE accepted by os.fspath, but the message wording focuses on Path/string.

Common situations: Passing a numeric identifier where a path was expected; passing a list of path components instead of using .join; passing a configuration object that wraps a path but is not os.PathLike.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/25597b2d15ef2b22. Report an issue: GitHub.