pytest-dev/pytest · error · ValueError
ini option has a type, which has no implicit default; pass…
Error message
ini option {name!r} has a {kind} type, which has no implicit default; pass an explicit `default` to `addini` What it means
Raised during addini() when the type is a union (tuple of tags) or a Literal of strings, but no explicit default was provided. Union and Literal types have no sensible implicit default (unlike 'string' which defaults to '' or 'bool' which defaults to False), so pytest requires an explicit default= argument.
Solutions
- Pass an explicit default: parser.addini('mode', type=Literal['a','b'], default='a')
- For union types, pick a default matching one member: parser.addini('val', type=int | str, default=0)
- If no default makes sense, reconsider whether a union/Literal type is appropriate
Example fix
# before
parser.addini('mode', type=Literal['fast', 'slow'])
# after
parser.addini('mode', type=Literal['fast', 'slow'], default='fast') Defensive patterns
Strategy: validation
Validate before calling
from typing import get_args, get_origin, Literal, Union, types
def needs_explicit_default(type_: object) -> bool:
if type_ is None:
return False
if get_origin(type_) in (Union, types.UnionType):
return True
if get_origin(type_) is Literal:
return True
return False
# Usage: if needs_explicit_default(my_type): pass default= to addini Type guard
from typing import get_args, get_origin, Literal, Union, types
def is_union_or_literal(type_: object) -> bool:
return get_origin(type_) in (Union, types.UnionType, Literal) Prevention
- Always pass default= when using a union or Literal type in addini
- Pick a default value matching one of the union members or Literal choices
- Remember that only scalar types (str, bool, int, float) get implicit defaults
When it happens
Trigger: Calling parser.addini('mode', type=Literal['a','b']) or parser.addini('val', type=int | str) without a default= parameter. The check `default is NOTSET and isinstance(ini_type, (tuple, _IniLiteral))` triggers.
Common situations: Adding a new ini option with a Literal or union type and forgetting the default. Refactoring an existing string option to a Literal without adding default=.
Related errors
- invalid type for ini option
- alias conflicts with existing configuration option
- is already an alias of
- invalid type for ini option
- no option named
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/86d28b0d435c4a90.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/config/argparsing.py:350
.. versionadded:: 9.0
The ``aliases`` parameter.
The value of configuration keys can be retrieved via a call to
:py:func:`config.getini(name) <pytest.Config.getini>`.
"""
ini_type: IniType
if type is None:
ini_type = "string"
elif get_origin(type) in (Union, types.UnionType):
ini_type = tuple(
_ini_type_to_member(name, member) for member in get_args(type)
)
else:
ini_type = _ini_type_to_member(name, type)
if default is NOTSET:
if isinstance(ini_type, (tuple, _IniLiteral)):
kind = "union" if isinstance(ini_type, tuple) else "Literal"
raise ValueError(
f"ini option {name!r} has a {kind} type, which has no "
"implicit default; pass an explicit `default` to `addini`"
)
default = get_ini_default_for_type(ini_type)
self._inidict[name] = (help, ini_type, default)
for alias in aliases:
if alias in self._inidict:
raise ValueError(
f"alias {alias!r} conflicts with existing configuration option"
)
if (already := self._ini_aliases.get(alias)) is not None:
raise ValueError(f"{alias!r} is already an alias of {already!r}")
self._ini_aliases[alias] = name
def get_ini_default_for_type(type: _IniTypeTag) -> Any:View on GitHub (pinned to 0d6fbdeffa)