pytest-dev/pytest · error · UsageError
{path}: Cannot use both [pytest] and [tool.pytest]/[tool.pyt
Error message
{path}: Cannot use both [pytest] and [tool.pytest]/[tool.pytest.ini_options] in the same file. Please use [pytest], which is what pytest's own configuration files use; the [tool.pytest] tables are meant for pyproject.toml. What it means
In a non-pyproject TOML file (e.g. pytest.toml), pytest accepts either the [pytest] table (its own native style) or the [tool.pytest]/[tool.pytest.ini_options] tables (the pyproject convention). Mixing both styles in one file is rejected because the precedence would be ambiguous and the [tool.*] tables are meant only for pyproject.toml.
Source
Thrown at src/_pytest/config/findpaths.py:221
def _load_custom_toml(path: Path) -> ConfigDict | None:
"""Load a TOML file with an arbitrary name, as passed via ``-c``.
Such a file reads its configuration from ``[pytest]``, like ``pytest.toml``
does -- the table pytest documents for its own files (#14705). The
``pyproject.toml`` tables ``[tool.pytest]``/``[tool.pytest.ini_options]``,
which arbitrary TOML files used to be parsed with exclusively, keep
working; using both styles in one file is an error.
"""
document = _parse_toml_file(path)
tool_pytest_config = _config_from_tool_pytest(path, document)
if tool_pytest_config is None:
return _config_from_pytest_table(path, document)
if "pytest" in document:
raise UsageError(
f"{path}: Cannot use both [pytest] and [tool.pytest]/"
"[tool.pytest.ini_options] in the same file. Please use [pytest], "
"which is what pytest's own configuration files use; the "
"[tool.pytest] tables are meant for pyproject.toml."
)
return tool_pytest_config
def _load_pyproject_toml(path: Path) -> ConfigDict | None:
"""Load a ``pyproject.toml``-style file.
Configuration is read from ``[tool.pytest]`` (TOML mode) or
``[tool.pytest.ini_options]`` (INI mode).
"""
return _config_from_tool_pytest(path, _parse_toml_file(path))
#: Loaders for the config files pytest discovers by name, in precedence order.View on GitHub (pinned to 0d6fbdeffa)
Solutions
- In pytest's own .toml files, keep only the [pytest] table and remove [tool.pytest] / [tool.pytest.ini_options].
- If you want the [tool.pytest] style, rename the file to pyproject.toml and remove the [pytest] table.
Example fix
// before [pytest] addopts = ["-ra"] [tool.pytest.ini_options] minversion = "7.0" // after [pytest] addopts = ["-ra"] minversion = "7.0"
Defensive patterns
Strategy: validation
Validate before calling
import tomllib, pathlib
def validate_pytest_toml_style(path: str) -> None:
doc = tomllib.loads(pathlib.Path(path).read_text())
has_pytest = 'pytest' in doc
has_tool_pytest = 'pytest' in doc.get('tool', {})
assert not (has_pytest and has_tool_pytest), \
'mixing [pytest] and [tool.pytest] in one file is not allowed' Type guard
null
Try / catch
null
Prevention
- Use [pytest] only in pytest-owned files (pytest.toml).
- Reserve [tool.pytest.*] for pyproject.toml.
When it happens
Trigger: A pytest.toml containing both a [pytest] table and a [tool.pytest] (or [tool.pytest.ini_options]) table; copy-pasting a pyproject snippet into pytest.toml alongside an existing [pytest] block.
Common situations: Renaming pyproject.toml to pytest.toml without stripping the [tool.pytest] wrapper; merging configs from different projects.
Related errors
- {path}: pytest configuration must be under a [pytest] table
- {path}: {exc}
- {path}: Cannot use both [tool.pytest] (native TOML types) an
- {self.inipath}: config option '{name}' expects one of {_ini_
- {self.inipath}: config option '{name}' expects a string, got
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/f3d2d517b7b4e4be.
Report an issue: GitHub.