pytest-dev/pytest · error · UsageError

must be a filename, given

Error message

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

What it means

Raised by filename_arg() (src/_pytest/config/__init__.py:290) when the supplied path is a directory. filename_arg is an argparse type validator registered for CLI options that require a plain file (e.g. --junitxml). It raises UsageError (pytest's user-facing error) so the message prints cleanly instead of as a traceback.

Solutions

  1. Point the option at a file path (e.g. --junitxml=reports/junit.xml); pytest will create it
  2. If you meant to set the output directory, use the directory-specific option (e.g. --basetemp uses directory_arg)
  3. Remove the trailing slash from the argument if you accidentally turned a file name into a directory

Example fix

// before
pytest --junitxml=reports/
// after
pytest --junitxml=reports/junit.xml
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

def is_file_not_dir(p: str) -> bool:
    import os
    return os.path.exists(p) and not os.path.isdir(p)

Try / catch

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

Prevention

When it happens

Trigger: Passing a directory path to a pytest CLI option whose argparse type is filename_arg - the validator at config/__init__.py:296-297 fires when os.path.isdir(path) is True.

Common situations: Running `pytest --junitxml=reports/` where reports/ exists as a directory; passing a directory to --resultlog, --cachefile, or any plugin option wired through filename_arg.

Related errors


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

Appendix: source

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

    from _pytest.deprecated import CONSOLE_MAIN

    warnings.warn(CONSOLE_MAIN, stacklevel=2)
    return _console_main()


class cmdline:  # compatibility namespace
    main = staticmethod(main)


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",

View on GitHub (pinned to 0d6fbdeffa)