pytest-dev/pytest · error · TypeError
{self.inipath}: config option '{name}' expects a string, got
Error message
{self.inipath}: config option '{name}' expects a string, got {builtins.type(value).__name__}: {value!r} What it means
Raised by Config._getini_value (config/__init__.py:1860-1867) when an ini option is registered with a Literal/choice type (an _IniLiteral carrying .choices) but the value read from config is not a Python str. Literal choices are checked verbatim with no coercion, in both ini and toml modes, so a non-string (e.g. a TOML int) is rejected before the choice membership test.
Source
Thrown at src/_pytest/config/__init__.py:1864
)
except (TypeError, ValueError) as e:
raise UsageError(str(e)) from e
def _getini_value(
self,
mode: Literal["ini", "toml"],
name: str,
canonical_name: str,
type: str | _IniLiteral,
value: object,
default: Any,
):
"""Convert a config value, read in the given mode, to the option's type."""
if isinstance(type, _IniLiteral):
# A Literal value is a plain string checked against the registered
# choices, without coercion, in both ini and toml modes.
if not isinstance(value, str):
raise TypeError(
f"{self.inipath}: config option '{name}' expects a string, "
f"got {builtins.type(value).__name__}: {value!r}"
)
if value not in type.choices:
raise ValueError(
f"{self.inipath}: config option '{name}' expects one of "
f"{_ini_type_repr(type)}, got {value!r}"
)
return value
if mode == "ini":
# In ini mode, values are always str | list[str].
assert isinstance(value, (str, list))
return self._getini_ini(name, canonical_name, type, value, default)
elif mode == "toml":
return self._getini_toml(name, canonical_name, type, value, default)
else:
assert_never(mode)
View on GitHub (pinned to 98b357f69e)
Solutions
- Quote the value in TOML so it parses as a string: my_opt = "strict".
- Verify the value is one of the documented choices for that option.
- If the option legitimately accepts non-string types, the plugin should register a non-Literal type (e.g. 'int').
Example fix
# before (pyproject.toml) [tool.pytest.ini_options] log_level = 20 # Literal choice expects a string # after log_level = "INFO"
Defensive patterns
Strategy: validation
Validate before calling
def ensure_str_choice(value):
if not isinstance(value, str):
raise TypeError(f'choice option must be a string, got {type(value).__name__}')
return value Type guard
def is_str_value(value) -> bool:
return isinstance(value, str) Try / catch
try:
config.getini(name)
except Exception:
# quote the value in pyproject.toml and rerun Prevention
- In TOML, always quote choice option values.
- Validate config values programmatically before invoking pytest in CI.
- Document the expected native type for each option.
When it happens
Trigger: Registering addini(..., type=..., choices=[...]) and supplying, via TOML, a value of native non-string type (int/bool/list) for that key. getini() or any ini read then trips this branch.
Common situations: pyproject.toml sets a choice option to a bare integer or boolean instead of a quoted string; converting an .ini file to .toml and dropping the quotes; a plugin registering choices but the user supplying the wrong native TOML type.
Related errors
- {self.inipath}: config option '{name}' expects one of {_ini_
- Expected an int string for option {name} of type integer, bu
- Expected a float string for option {name} of type float, but
- {self.inipath}: config option '{name}' expects a list for ty
- {self.inipath}: config option '{name}' expects a list for ty
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/8587a2c455b25ae2.json.
Report an issue: GitHub.