{"record":{"id":"8587a2c455b25ae2","repo":"pytest-dev/pytest","slug":"self-inipath-config-option-name-expects-a-s","errorCode":null,"errorMessage":"{self.inipath}: config option '{name}' expects a string, got {builtins.type(value).__name__}: {value!r}","messagePattern":"(.+?): config option '(.+?)' expects a string, got (.+?): (.+?)","errorType":"exception","errorClass":"UsageError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/__init__.py","lineNumber":1864,"sourceCode":"            )\n        except (TypeError, ValueError) as e:\n            raise UsageError(str(e)) from e\n\n    def _getini_value(\n        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","sourceCodeStart":1846,"sourceCodeEnd":1882,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/config/__init__.py#L1846-L1882","documentation":"Raised by _getini_value() at config/__init__.py:1864-1867 when an ini option registered with a Literal[...] type (normalized to _IniLiteral, argparsing.py:47) receives a non-string value. The check at capture.py:1860-1867 enforces that Literal choices are matched against a plain string in both ini and toml modes; passing a TOML int/bool/list triggers TypeError, which is then converted to UsageError by the outer handler at config/__init__.py:1847-1848.","triggerScenarios":"A plugin registers addini('mode', type=Literal['a','b','c']) and the user writes `mode = 1` or `mode = true` in pyproject.toml. The non-string check at capture.py:1863 raises TypeError.","commonSituations":"TOML-native values for choice options (where the user assumed the choice would accept any truthy value or numeric key); migrating ini configs to pyproject.toml and losing the implicit string quoting; plugin docs not making clear that the option is choice-constrained.","solutions":["Quote the value so it is parsed as a TOML string: mode = \"a\"","Pick one of the documented Literal choices","If you control the plugin, broaden the type to Literal[...] | str or document the allowed strings clearly"],"exampleFix":"// before\n# pyproject.toml\n[tool.pytest.ini_options]\nlog_level = 1   # Literal['DEBUG','INFO',...]\n// after\nlog_level = \"DEBUG\"","handlingStrategy":"validation","validationCode":"# Ensure choice-typed ini values are TOML strings\nimport tomllib\ncfg = tomllib.loads(open('pyproject.toml').read())\nfor k, v in cfg.get('tool',{}).get('pytest',{}).get('ini_options',{}).items():\n    if not isinstance(v, str) and not isinstance(v, (list,)):\n        print(f'{k} should be a string, got {type(v).__name__}')","typeGuard":"def is_str_or_list(v) -> bool:\n    return isinstance(v, str) or (isinstance(v, list) and all(isinstance(x, str) for x in v))","tryCatchPattern":"from _pytest.config import UsageError\ntry:\n    val = config.getini('mode')\nexcept UsageError as e:\n    print(f'Set mode to a quoted string in pyproject.toml: {e}')","preventionTips":["Always quote choice values in pyproject.toml even when they look numeric","Document Literal options with explicit TOML examples in plugin docs","Validate pyproject.toml [tool.pytest.ini_options] in a pre-commit hook"],"tags":["config","ini","toml","literal","validation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}