pytest-dev/pytest · error · UsageError
{path}: Cannot use both [tool.pytest] (native TOML types) an
Error message
{path}: Cannot use both [tool.pytest] (native TOML types) and [tool.pytest.ini_options] (string-based INI format) simultaneously. Please use [tool.pytest] with native TOML types (recommended) or [tool.pytest.ini_options] for backwards compatibility. What it means
A single pyproject.toml may configure pytest via either [tool.pytest] (native TOML types, the modern style) or [tool.pytest.ini_options] (legacy string-based INI emulation), but not both. pytest detects content in [tool.pytest] outside ini_options alongside ini_options content and raises UsageError to avoid type ambiguity.
Source
Thrown at src/_pytest/config/findpaths.py:167
f"{', '.join(top_level_options)})"
)
return None
def _config_from_tool_pytest(
path: Path, config: dict[str, object]
) -> ConfigDict | None:
"""Return the configuration in the ``[tool.pytest]`` tables of a parsed
TOML document, or None if it has none."""
tool_pytest = config.get("tool", {}).get("pytest", {}) # type: ignore[attr-defined]
# Check for toml mode config: [tool.pytest] with content outside of ini_options.
toml_config = {k: v for k, v in tool_pytest.items() if k != "ini_options"}
# Check for ini mode config: [tool.pytest.ini_options].
ini_config = tool_pytest.get("ini_options", None)
if toml_config and ini_config:
raise UsageError(
f"{path}: Cannot use both [tool.pytest] (native TOML types) and "
"[tool.pytest.ini_options] (string-based INI format) simultaneously. "
"Please use [tool.pytest] with native TOML types (recommended) "
"or [tool.pytest.ini_options] for backwards compatibility."
)
if toml_config:
# TOML mode - preserve native TOML types.
return {
k: ConfigValue(v, origin="file", mode="toml")
for k, v in toml_config.items()
}
if ini_config is not None:
# INI mode - TOML supports richer data types than INI files, but we need to
# convert all scalar values to str for compatibility with the INI system.
def make_scalar(v: object) -> str | list[str]:
return v if isinstance(v, list) else str(v)View on GitHub (pinned to 0d6fbdeffa)
Solutions
- Choose one style: delete [tool.pytest.ini_options] and keep [tool.pytest] (recommended, native types).
- Or delete [tool.pytest] content outside ini_options and keep [tool.pytest.ini_options] for backwards compatibility.
- Re-run pytest to confirm the conflict is gone.
Example fix
// before [tool.pytest] addopts = ["-ra"] [tool.pytest.ini_options] minversion = "7.0" // after [tool.pytest] addopts = ["-ra"] minversion = "7.0"
Defensive patterns
Strategy: validation
Validate before calling
import tomllib, pathlib
def validate_single_style(path: str) -> None:
doc = tomllib.loads(pathlib.Path(path).read_text())
tp = doc.get('tool', {}).get('pytest', {})
toml_part = {k: v for k, v in tp.items() if k != 'ini_options'}
assert not (toml_part and tp.get('ini_options')), \
'use either [tool.pytest] or [tool.pytest.ini_options], not both' Type guard
null
Try / catch
null
Prevention
- Pick one TOML style and document it in the project README.
- When migrating, delete the old block in the same commit.
When it happens
Trigger: Having [tool.pytest] addopts = [...] and [tool.pytest.ini_options] addopts = "..." in the same pyproject.toml; gradual migration left behind both blocks.
Common situations: Migrating from ini_options to native [tool.pytest] and forgetting to delete the old block; merging config from two snippets that used different styles.
Related errors
- {path}: {exc}
- {path}: pytest configuration must be under a [pytest] table
- {path}: Cannot use both [pytest] and [tool.pytest]/[tool.pyt
- {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/28425034ae5d36e6.
Report an issue: GitHub.