pytest-dev/pytest · error · ValueError
ini option {name!r} has a {kind} type, which has no implicit
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 by Parser.addini() when the type is a union (e.g. int | str) or a Literal of strings, but no explicit default= argument was provided. These compound types have no single sensible implicit default, so pytest refuses to guess and requires the plugin author to pass one.
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 98b357f69e)
Solutions
- Pass an explicit default: parser.addini('mode', type=Literal['a','b'], default='a').
- Choose a default that matches one of the union members / Literal choices.
- If you want a None default, pass default=None explicitly.
Example fix
# before
parser.addini('mode', type=Literal['fast','slow'], help='run mode')
# after
parser.addini('mode', type=Literal['fast','slow'], default='fast', help='run mode') Defensive patterns
Strategy: validation
Validate before calling
from typing import get_origin, get_args, Literal, Union, types
def needs_default(type_: object) -> bool:
if get_origin(type_) in (Union, types.UnionType):
return True
if get_origin(type_) is Literal:
return True
return False
# enforce: always pass default= when needs_default(type_) is True Prevention
- Always pass an explicit default= when using union or Literal ini types.
- Add a registration smoke test in CI to catch missing defaults early.
When it happens
Trigger: Calling parser.addini('myopt', type=int | str) or parser.addini('mode', type=Literal['a','b']) without a default= keyword. The check at line 347-353 sees default is NOTSET and ini_type is a tuple or _IniLiteral.
Common situations: Adding a new Literal/union ini option and forgetting the default; refactoring a simple-typed option into a union without adding a default.
Related errors
- invalid type for ini option {name!r}: Literal choices must b
- invalid type for ini option {name!r}: {type_!r} (expected on
- alias {alias!r} conflicts with existing configuration option
- {alias!r} is already an alias of {already!r}
- help argument cannot be None for {name}
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/86d28b0d435c4a90.json.
Report an issue: GitHub.