pytest-dev/pytest · error · TypeError
parameter needs to be a string, but given
Error message
{param} parameter needs to be a string, but {g} given What it means
_check_record_param_type (junitxml.py:337) validates that the NAME argument passed to record_testsuite_property (and similarly record_property) is a str. If the caller passes a non-string name (int, tuple, etc.), it raises TypeError naming the bad type. The VALUE may be any object; only the name must be a string because it becomes an XML attribute/tag name.
Solutions
- Cast the name to str before calling: record_testsuite_property(str(name), value).
- Ensure name values are string literals or string-typed variables.
- Double-check argument order: (name, value).
Example fix
// before record_testsuite_property(run_id, 'passed') # run_id is int // after record_testsuite_property(str(run_id), 'passed')
Defensive patterns
Strategy: type-guard
Validate before calling
# Validate name is str before recording a property
def safe_suite_property(record_fn, name, value):
if not isinstance(name, str):
raise TypeError(f'name must be str, got {type(name).__name__}')
record_fn(name, value) Type guard
def is_property_name(v) -> bool:
return isinstance(v, str) and v.isidentifier() Prevention
- Always cast names to str.
- Use string literals or string-typed variables for property names.
- Remember argument order: (name, value).
When it happens
Trigger: Calling record_testsuite_property(123, 'v') or record_testsuite_property(('a','b'), 'v'); passing a variable expected to be a string but holding an int; looping over keys without casting.
Common situations: Programmatically generating property names from counters/enums without str(); mixing up argument order (passing value first); refactoring that changes name type.
Related errors
- absolute tolerance can't be NaN.
- absolute tolerance can't be negative
- absolute tolerance for a scalar value must be an int, float…
- alias conflicts with existing configuration option
- is already an alias of
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/1a2db5149e9289dc.
Report an issue: GitHub.
Appendix: source
Thrown at src/_pytest/junitxml.py:337
pass
attr_func = add_attr_noop
xml = request.config.stash.get(xml_key, None)
if xml is not None:
node_reporter = xml.node_reporter(request.node.nodeid)
attr_func = node_reporter.add_attribute
return attr_func
def _check_record_param_type(param: str, v: str) -> None:
"""Used by record_testsuite_property to check that the given parameter name is of the proper
type."""
__tracebackhide__ = True
if not isinstance(v, str):
msg = "{param} parameter needs to be a string, but {g} given" # type: ignore[unreachable]
raise TypeError(msg.format(param=param, g=type(v).__name__))
@pytest.fixture(scope="session")
def record_testsuite_property(request: FixtureRequest) -> Callable[[str, object], None]:
"""Record a new ``<property>`` tag as child of the root ``<testsuite>``.
This is suitable to writing global information regarding the entire test
suite, and is compatible with ``xunit2`` JUnit family.
This is a ``session``-scoped fixture which is called with ``(name, value)``. Example:
.. code-block:: python
def test_foo(record_testsuite_property):
record_testsuite_property("ARCH", "PPC")
record_testsuite_property("STORAGE_TYPE", "CEPH")
:param name:View on GitHub (pinned to 0d6fbdeffa)