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

  1. Choose one style: delete [tool.pytest.ini_options] and keep [tool.pytest] (recommended, native types).
  2. Or delete [tool.pytest] content outside ini_options and keep [tool.pytest.ini_options] for backwards compatibility.
  3. 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

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


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