pytest-dev/pytest · error · ValueError

invalid part specification {name!r}

Error message

invalid part specification {name!r}

What it means

Raised inside LocalPath._getbyspec() when a requested spec part name is not one of the recognized tokens ('drive','dirname','basename','purebasename','ext'). The method splits a comma-separated spec string and appends each requested part to the result; an unknown token falls through to the else branch and raises ValueError. This is an internal helper invoked by new() and parts().

Source

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

                res.append(parts[0])
            elif name == "dirname":
                res.append(self.sep.join(parts[:-1]))
            else:
                basename = parts[-1]
                if name == "basename":
                    res.append(basename)
                else:
                    i = basename.rfind(".")
                    if i == -1:
                        purebasename, ext = basename, ""
                    else:
                        purebasename, ext = basename[:i], basename[i:]
                    if name == "purebasename":
                        res.append(purebasename)
                    elif name == "ext":
                        res.append(ext)
                    else:
                        raise ValueError(f"invalid part specification {name!r}")
        return res

    def dirpath(self, *args, **kwargs):
        """Return the directory path joined with any given path arguments."""
        if not kwargs:
            path = object.__new__(self.__class__)
            path.strpath = dirname(self.strpath)
            if args:
                path = path.join(*args)
            return path
        return self.new(basename="").join(*args, **kwargs)

    def join(self, *args: os.PathLike[str], abs: bool = False) -> LocalPath:
        """Return a new path by appending all 'args' as path
        components.  if abs=1 is used restart from root if any
        of the args is an absolute path.
        """
        sep = self.sep

View on GitHub (pinned to 0d6fbdeffa)

Solutions

  1. Use only the supported spec tokens: drive, dirname, basename, purebasename, ext.
  2. Avoid calling the private _getbyspec directly — use the public .parts() or .purebasename/.ext properties.
  3. If you need a custom decomposition, split the path string yourself with os.path or pathlib.

Example fix

// before
parts = p._getbyspec('dirname,stemname')
// after
parts = p._getbyspec('dirname,purebasename')
Defensive patterns

Strategy: validation

Validate before calling

VALID_PARTS = {'drive','dirname','basename','purebasename','ext'}
def safe_getbyspec(path, spec):
    names = [s.strip() for s in spec.split(',')]
    bad = [n for n in names if n not in VALID_PARTS]
    if bad:
        raise ValueError(f'unknown parts: {bad}')
    return path._getbyspec(spec)

Type guard

def is_valid_part(name: str) -> bool:
    return name in {'drive','dirname','basename','purebasename','ext'}

Prevention

When it happens

Trigger: Calling path._getbyspec('drive,dirname,foo') directly with a typo; an internal caller (e.g. parts()) passing an unsupported spec token; monkeypatching or extending the spec vocabulary incorrectly.

Common situations: Direct misuse of the private _getbyspec API; bugs in plugins or forks that reference non-existent path components; typo in a spec string passed through from custom code.

Related errors


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