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

  1. 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.
  2. Or keep [tool.pytest.ini_options] only for backwards compatibility and remove the [tool.pytest] table.
  3. 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

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


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/60ea4c436ba03cdb.json. Report an issue: GitHub.