pytest-dev/pytest · error · UsageError

must be a directory, given

Error message

{optname} must be a directory, given: {path}

What it means

Raised by directory_arg() (src/_pytest/config/__init__.py:301) when the supplied path is NOT a directory. directory_arg is the argparse type validator paired with filename_arg (config/__init__.py:290); options that need a directory use it. It raises UsageError when os.path.isdir(path) is False so the user gets a short message.

Solutions

  1. Point the option at an existing directory (mkdir -p first if needed)
  2. For --rootdir, point at the project root, not a source file inside it
  3. Drop the option and let pytest infer the directory from the args

Example fix

// before
pytest --rootdir=src/app.py
// after
pytest --rootdir=src
Defensive patterns

Strategy: validation

Validate before calling

import os
if not os.path.isdir(path):
    raise ValueError(f'{optname} expects a directory, got {path}')

Type guard

def is_dir(p: str) -> bool:
    import os
    return os.path.isdir(p)

Try / catch

from _pytest.config import directory_arg
try:
    p = directory_arg(user_input, 'opt')
except UsageError as e:
    print(e)

Prevention

When it happens

Trigger: Passing a file path or non-existent path to a CLI option whose argparse type is directory_arg (config/__init__.py:307-308). Common options include --rootdir and --basetemp.

Common situations: `pytest --rootdir=setup.py` (file, not dir); `pytest --basetemp=/tmp/does/not/exist`; mis-pasting a project file path where a directory was expected.

Related errors


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

Appendix: source

Thrown at src/_pytest/config/__init__.py:308

def filename_arg(path: str, optname: str) -> str:
    """Argparse type validator for filename arguments.

    :path: Path of filename.
    :optname: Name of the option.
    """
    if os.path.isdir(path):
        raise UsageError(f"{optname} must be a filename, given: {path}")
    return path


def directory_arg(path: str, optname: str) -> str:
    """Argparse type validator for directory arguments.

    :path: Path of directory.
    :optname: Name of the option.
    """
    if not os.path.isdir(path):
        raise UsageError(f"{optname} must be a directory, given: {path}")
    return path


# Plugins that cannot be disabled via "-p no:X" currently.
essential_plugins = (
    "mark",
    "main",
    "runner",
    "fixtures",
    "helpconfig",  # Provides -p.
)

default_plugins = (
    *essential_plugins,
    "python",
    "terminal",
    "debugging",
    "unittest",

View on GitHub (pinned to 0d6fbdeffa)