{"record":{"id":"28425034ae5d36e6","repo":"pytest-dev/pytest","slug":"path-cannot-use-both-tool-pytest-native-toml","errorCode":null,"errorMessage":"{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.","messagePattern":"(.+?): 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\\.","errorType":"exception","errorClass":"UsageError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/findpaths.py","lineNumber":167,"sourceCode":"            f\"{', '.join(top_level_options)})\"\n        )\n    return None\n\n\ndef _config_from_tool_pytest(\n    path: Path, config: dict[str, object]\n) -> ConfigDict | None:\n    \"\"\"Return the configuration in the ``[tool.pytest]`` tables of a parsed\n    TOML document, or None if it has none.\"\"\"\n    tool_pytest = config.get(\"tool\", {}).get(\"pytest\", {})  # type: ignore[attr-defined]\n\n    # Check for toml mode config: [tool.pytest] with content outside of ini_options.\n    toml_config = {k: v for k, v in tool_pytest.items() if k != \"ini_options\"}\n    # Check for ini mode config: [tool.pytest.ini_options].\n    ini_config = tool_pytest.get(\"ini_options\", None)\n\n    if toml_config and ini_config:\n        raise UsageError(\n            f\"{path}: Cannot use both [tool.pytest] (native TOML types) and \"\n            \"[tool.pytest.ini_options] (string-based INI format) simultaneously. \"\n            \"Please use [tool.pytest] with native TOML types (recommended) \"\n            \"or [tool.pytest.ini_options] for backwards compatibility.\"\n        )\n\n    if toml_config:\n        # TOML mode - preserve native TOML types.\n        return {\n            k: ConfigValue(v, origin=\"file\", mode=\"toml\")\n            for k, v in toml_config.items()\n        }\n\n    if ini_config is not None:\n        # INI mode - TOML supports richer data types than INI files, but we need to\n        # convert all scalar values to str for compatibility with the INI system.\n        def make_scalar(v: object) -> str | list[str]:\n            return v if isinstance(v, list) else str(v)","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/config/findpaths.py#L149-L185","documentation":"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.","triggerScenarios":"Having [tool.pytest] addopts = [...] and [tool.pytest.ini_options] addopts = \"...\" in the same pyproject.toml; gradual migration left behind both blocks.","commonSituations":"Migrating from ini_options to native [tool.pytest] and forgetting to delete the old block; merging config from two snippets that used different styles.","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."],"exampleFix":"// before\n[tool.pytest]\naddopts = [\"-ra\"]\n\n[tool.pytest.ini_options]\nminversion = \"7.0\"\n// after\n[tool.pytest]\naddopts = [\"-ra\"]\nminversion = \"7.0\"","handlingStrategy":"validation","validationCode":"import tomllib, pathlib\n\ndef validate_single_style(path: str) -> None:\n    doc = tomllib.loads(pathlib.Path(path).read_text())\n    tp = doc.get('tool', {}).get('pytest', {})\n    toml_part = {k: v for k, v in tp.items() if k != 'ini_options'}\n    assert not (toml_part and tp.get('ini_options')), \\\n        'use either [tool.pytest] or [tool.pytest.ini_options], not both'","typeGuard":"null","tryCatchPattern":"null","preventionTips":["Pick one TOML style and document it in the project README.","When migrating, delete the old block in the same commit."],"tags":["config","toml","pyproject","migration"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}