{"record":{"id":"04a60174c1336e08","repo":"pytest-dev/pytest","slug":"invalid-type-for-ini-option-name-r-literal-choi","errorCode":null,"errorMessage":"invalid type for ini option {name!r}: Literal choices must be strings, got {choices!r}","messagePattern":"invalid type for ini option (.+?): Literal choices must be strings, got (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/config/argparsing.py","lineNumber":87,"sourceCode":"def _ini_type_to_tag(name: str, type_: object) -> _IniTypeTag:\n    \"\"\"Normalize one member of an `addini(type=...)` argument to a string tag.\"\"\"\n    try:\n        return _INI_TYPES[type_]\n    except (KeyError, TypeError):  # TypeError: unhashable type_\n        raise ValueError(\n            f\"invalid type for ini option {name!r}: {type_!r} (expected one of \"\n            f\"{', '.join(repr(tag) for tag in get_args(_IniTypeTag))}, one of \"\n            \"the types str, bool, int, float, a union of these types such as \"\n            \"`int | str`, or a `Literal` of strings)\"\n        ) from None\n\n\ndef _ini_type_to_member(name: str, type_: object) -> _IniTypeTag | _IniLiteral:\n    \"\"\"Normalize one member of an `addini(type=...)` argument.\"\"\"\n    if get_origin(type_) is Literal:\n        choices = get_args(type_)\n        if not all(isinstance(choice, str) for choice in choices):\n            raise ValueError(\n                f\"invalid type for ini option {name!r}: Literal choices \"\n                f\"must be strings, got {choices!r}\"\n            )\n        return _IniLiteral(choices)\n    return _ini_type_to_tag(name, type_)\n\n\ndef _ini_type_repr(type: IniType) -> str:\n    \"\"\"Render an ini option type for --help output and error messages.\"\"\"\n    if isinstance(type, _IniLiteral):\n        return \" | \".join(repr(choice) for choice in type.choices)\n    if isinstance(type, tuple):\n        return \" | \".join(_ini_type_repr(member) for member in type)\n    return type\n\n\ndef _get_argparse_dest(opts: Sequence[str]) -> str:\n    long_opts = [opt for opt in opts if opt.startswith(\"--\")]","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/config/argparsing.py#L69-L105","documentation":"Raised by _ini_type_to_member() during addini() when a Literal type is used for the type argument but not all of its choices are strings. Literal types for ini options must contain only str choices. The error names the invalid choices.","triggerScenarios":"Calling parser.addini('mode', type=Literal['fast', 42]) — the integer 42 is not a string. The check `all(isinstance(choice, str) for choice in choices)` fails inside the get_origin(type_) is Literal branch.","commonSituations":"Mixing string and non-string choices in a Literal type. Using Literal[int, str] expecting numeric support. Copying a Literal from application code that includes non-string members.","solutions":["Ensure all Literal choices are strings: change Literal['fast', 42] to Literal['fast', '42']","If numeric values are needed, use type='string' and validate in your plugin code","Use a union of recognized scalar types (int | str) instead of Literal for mixed numeric/string input"],"exampleFix":"# before\nparser.addini('mode', type=Literal['fast', 42])\n\n# after\nparser.addini('mode', type=Literal['fast', '42'])","handlingStrategy":"type-guard","validationCode":"from typing import get_args, get_origin, Literal\ndef validate_literal_choices(type_: object) -> bool:\n    if get_origin(type_) is Literal:\n        choices = get_args(type_)\n        return all(isinstance(c, str) for c in choices)\n    return True","typeGuard":"from typing import get_args, get_origin, Literal\ndef is_string_literal(type_: object) -> bool:\n    if get_origin(type_) is not Literal:\n        return False\n    return all(isinstance(c, str) for c in get_args(type_))","tryCatchPattern":null,"preventionTips":["Ensure all Literal choices are strings: Literal['a', 'b']","Do not mix string and non-string choices in a Literal type","Use a union type (int | str) if numeric input is needed instead of Literal"],"tags":["pytest","config","addini","type-validation","literal","plugin-api"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}