{"id":"aaeea2877ccafd18","repo":"pytest-dev/pytest","slug":"self-inipath-config-option-name-expects-one-aaeea2","errorCode":null,"errorMessage":"{self.inipath}: config option '{name}' expects one of {_ini_type_repr(type)}, got {value!r}","messagePattern":"(.+?): config option '(.+?)' expects one of (.+?), got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/__init__.py","lineNumber":1869,"sourceCode":"        self,\n        mode: Literal[\"ini\", \"toml\"],\n        name: str,\n        canonical_name: str,\n        type: str | _IniLiteral,\n        value: object,\n        default: Any,\n    ):\n        \"\"\"Convert a config value, read in the given mode, to the option's type.\"\"\"\n        if isinstance(type, _IniLiteral):\n            # A Literal value is a plain string checked against the registered\n            # choices, without coercion, in both ini and toml modes.\n            if not isinstance(value, str):\n                raise TypeError(\n                    f\"{self.inipath}: config option '{name}' expects a string, \"\n                    f\"got {builtins.type(value).__name__}: {value!r}\"\n                )\n            if value not in type.choices:\n                raise ValueError(\n                    f\"{self.inipath}: config option '{name}' expects one of \"\n                    f\"{_ini_type_repr(type)}, got {value!r}\"\n                )\n            return value\n        if mode == \"ini\":\n            # In ini mode, values are always str | list[str].\n            assert isinstance(value, (str, list))\n            return self._getini_ini(name, canonical_name, type, value, default)\n        elif mode == \"toml\":\n            return self._getini_toml(name, canonical_name, type, value, default)\n        else:\n            assert_never(mode)\n\n    def _getini_ini(\n        self,\n        name: str,\n        canonical_name: str,\n        type: str,","sourceCodeStart":1851,"sourceCodeEnd":1887,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/config/__init__.py#L1851-L1887","documentation":"Raised by Config._getini_value (config/__init__.py:1868-1872) for a Literal/choice ini option: the value IS a string but it is not present in the registered .choices tuple. This is the standard 'value not in allowed choices' rejection, surfaced as UsageError.","triggerScenarios":"Supplying a string for a choice option that is not in the allowed set registered via addini(choices=[...]). Common with log_level, log_auto_indent, or custom plugin choice options.","commonSituations":"Typo in a choice value (e.g. 'WARRNING' vs 'WARNING'); using a value valid in an older pytest version but removed/renamed; passing a lowercase value when choices are uppercase.","solutions":["Consult the error's 'expects one of' list and pick one of the named choices.","Fix casing/typos to match a registered choice exactly.","If a custom plugin, extend addini choices to include the new value, or switch to a free-form type."],"exampleFix":"# before (pyproject.toml)\n[tool.pytest.ini_options]\nlog_level = \"informational\"\n\n# after\nlog_level = \"INFO\"","handlingStrategy":"validation","validationCode":"def validate_choice(value, choices):\n    if value not in choices:\n        raise ValueError(f'{value!r} not in {choices}')\n    return value","typeGuard":"def is_allowed_choice(value, choices) -> bool:\n    return isinstance(value, str) and value in choices","tryCatchPattern":"try:\n    config.getini(name)\nexcept Exception as e:\n    # pick the closest valid choice from the message and update config","preventionTips":["Match choice casing exactly (often uppercase).","Cross-check custom choice lists against addini(choices=[...]).","Use a config linter for pyproject.toml [tool.pytest.ini_options]."],"tags":["config","ini","choices","invalid-value","pytest"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}