pytest-dev/pytest · error · ValueError

invalid type for ini option

Error message

invalid type for ini option {name!r}: {type_!r} (expected one of {tags}, one of the types str, bool, int, float, a union of these types such as `int | str`, or a `Literal` of strings)

What it means

Raised by _ini_type_to_tag() during addini() when the type argument (or a member of a union type) is not one of the recognized ini types. Valid types are the Python types str, bool, int, float, or the string tags 'string','bool','int','float','paths','pathlist','args','linelist'. The error lists the valid tags and explains union/Literal syntax.

Solutions

  1. Use one of the valid string tags: 'string', 'bool', 'int', 'float', 'paths', 'pathlist', 'args', 'linelist'
  2. Or use the corresponding Python type: str, bool, int, float
  3. For multiple string choices, use Literal['a','b','c']
  4. For unions, use only valid members: int | str

Example fix

# before
parser.addini('my_opt', type=list)

# after
parser.addini('my_opt', type='linelist')
Defensive patterns

Strategy: type-guard

Validate before calling

VALID_INI_TAGS = {'string', 'bool', 'int', 'float', 'paths', 'pathlist', 'args', 'linelist'}
VALID_INI_TYPES = {str, bool, int, float}
def validate_addini_type(type_: object) -> bool:
    if type_ is None:
        return True
    if type_ in VALID_INI_TAGS or type_ in VALID_INI_TYPES:
        return True
    return False

Type guard

from typing import get_args, get_origin, Literal
VALID_TAGS = {'string', 'bool', 'int', 'float', 'paths', 'pathlist', 'args', 'linelist'}
VALID_TYPES = {str, bool, int, float}
def is_valid_ini_type_member(t: object) -> bool:
    return t in VALID_TAGS or t in VALID_TYPES

Prevention

When it happens

Trigger: Calling parser.addini('name', type=list) or type=dict or type=SomeEnum — none of these are recognized. Also triggered by passing an unhashable type (TypeError in the dict lookup). The _INI_TYPES dict lookup raises KeyError or TypeError.

Common situations: Passing Python collection types (list, dict, set, tuple) as the type. Passing an Enum or arbitrary class. Passing a non-type object. Using a union that includes an invalid member (e.g., int | list).

Related errors


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

Appendix: source

Thrown at src/_pytest/config/argparsing.py:74

#: ``int | str``).
IniType: TypeAlias = _IniTypeTag | _IniLiteral | tuple[_IniTypeTag | _IniLiteral, ...]

#: Maps each string tag or plain Python type accepted by :meth:`Parser.addini`
#: for its ``type`` argument to the normalized string tag.
_INI_TYPES: dict[object, _IniTypeTag] = {tag: tag for tag in get_args(_IniTypeTag)} | {
    str: "string",
    bool: "bool",
    int: "int",
    float: "float",
}


def _ini_type_to_tag(name: str, type_: object) -> _IniTypeTag:
    """Normalize one member of an `addini(type=...)` argument to a string tag."""
    try:
        return _INI_TYPES[type_]
    except (KeyError, TypeError):  # TypeError: unhashable type_
        raise ValueError(
            f"invalid type for ini option {name!r}: {type_!r} (expected one of "
            f"{', '.join(repr(tag) for tag in get_args(_IniTypeTag))}, one of "
            "the types str, bool, int, float, a union of these types such as "
            "`int | str`, or a `Literal` of strings)"
        ) from None


def _ini_type_to_member(name: str, type_: object) -> _IniTypeTag | _IniLiteral:
    """Normalize one member of an `addini(type=...)` argument."""
    if get_origin(type_) is Literal:
        choices = get_args(type_)
        if not all(isinstance(choice, str) for choice in choices):
            raise ValueError(
                f"invalid type for ini option {name!r}: Literal choices "
                f"must be strings, got {choices!r}"
            )
        return _IniLiteral(choices)
    return _ini_type_to_tag(name, type_)

View on GitHub (pinned to 0d6fbdeffa)