pytest-dev/pytest · error · UsageError
{filepath}: Cannot use both [tool.pytest] (native TOML types
Error message
{filepath}: 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
Raised when a pyproject.toml contains BOTH a [tool.pytest] table (native TOML types, the newer recommended mode) AND a [tool.pytest.ini_options] table (legacy string-based INI mode). pytest cannot merge the two semantics, so it refuses to load and asks the user to pick one mode.
Source
Thrown at src/_pytest/config/findpaths.py:138
raise UsageError(
f"{filepath}: pytest configuration must be under a "
f"[pytest] table (found top-level options: "
f"{', '.join(top_level_options)})"
)
# "pytest.toml" files are always the source of configuration, even if empty.
return {}
# pyproject.toml uses [tool.pytest] or [tool.pytest.ini_options].
else:
tool_pytest = config.get("tool", {}).get("pytest", {})
# 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"{filepath}: 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()
}
elif 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 98b357f69e)
Solutions
- Consolidate into [tool.pytest] (native TOML types, recommended): move all keys out of ini_options into [tool.pytest] directly and delete the [tool.pytest.ini_options] table.
- Or keep [tool.pytest.ini_options] only for backwards compatibility and remove the [tool.pytest] table.
- Re-run pytest after editing to confirm the conflict is resolved.
Example fix
# before [tool.pytest] addopts = '-v' [tool.pytest.ini_options] testpaths = ['tests'] # after (native TOML mode) [tool.pytest] addopts = '-v' testpaths = ['tests']
Defensive patterns
Strategy: validation
Validate before calling
import sys, pathlib
try:
import tomllib
except ImportError:
import tomli as tomllib
def validate_no_dual_pytest_tables(path: pathlib.Path) -> None:
config = tomllib.loads(path.read_text(encoding='utf-8'))
tool_pytest = config.get('tool', {}).get('pytest', {})
toml_keys = {k: v for k, v in tool_pytest.items() if k != 'ini_options'}
has_ini = 'ini_options' in tool_pytest
if toml_keys and has_ini:
raise ValueError(f'{path}: cannot use both [tool.pytest] and [tool.pytest.ini_options]') Prevention
- Choose one config mode ([tool.pytest] recommended) and delete the other during migration.
- Review pyproject.toml after merging config snippets from external sources.
- Add a CI lint that rejects simultaneous presence of both tables.
When it happens
Trigger: A pyproject.toml with both [tool.pytest] keys (e.g. addopts directly) and a [tool.pytest.ini_options] subsection. The check at line 133-143 detects both toml_config (keys under [tool.pytest] excluding ini_options) and ini_config (the ini_options subtable).
Common situations: Partially migrating from [tool.pytest.ini_options] to [tool.pytest] and leaving remnants of both; merging config snippets from different sources/tutorials; copy-pasting a modern example while keeping old ini_options keys.
Related errors
- {filepath}: pytest configuration must be under a [pytest] ta
- {filepath}: {exc}
- {self.inipath}: config option '{name}' expects one of {_ini_
- {self.inipath}: config option '{name}' expects a string, got
- {self.inipath}: config option '{name}' expects a list for ty
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/60ea4c436ba03cdb.json.
Report an issue: GitHub.