{"record":{"id":"0aa1a81270f1bbbe","repo":"pytest-dev/pytest","slug":"is-not-a-string-or-pytest-mark-marker","errorCode":null,"errorMessage":"is not a string or pytest.mark.* Marker","messagePattern":"is not a string or pytest\\.mark\\.\\* Marker","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/nodes.py","lineNumber":323,"sourceCode":"        chain.reverse()\n        return chain\n\n    def add_marker(self, marker: str | MarkDecorator, append: bool = True) -> None:\n        \"\"\"Dynamically add a marker object to the node.\n\n        :param marker:\n            The marker.\n        :param append:\n            Whether to append the marker, or prepend it.\n        \"\"\"\n        from _pytest.mark import MARK_GEN\n\n        if isinstance(marker, MarkDecorator):\n            marker_ = marker\n        elif isinstance(marker, str):\n            marker_ = getattr(MARK_GEN, marker)\n        else:\n            raise ValueError(\"is not a string or pytest.mark.* Marker\")\n        self.keywords[marker_.name] = marker_\n        if append:\n            self.own_markers.append(marker_.mark)\n        else:\n            self.own_markers.insert(0, marker_.mark)\n\n    def iter_markers(self, name: str | None = None) -> Iterator[Mark]:\n        \"\"\"Iterate over all markers of the node.\n\n        :param name: If given, filter the results by the name attribute.\n        :returns: An iterator of the markers of the node.\n        \"\"\"\n        return (x[1] for x in self.iter_markers_with_node(name=name))\n\n    def iter_markers_with_node(\n        self, name: str | None = None\n    ) -> Iterator[tuple[Node, Mark]]:\n        \"\"\"Iterate over all markers of the node.","sourceCodeStart":305,"sourceCodeEnd":341,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/nodes.py#L305-L341","documentation":"Raised by Node.add_marker (via the marker path at lines 320-324) when the marker argument is neither a str nor a MarkDecorator. pytest accepts either a dotted-name string (resolved against MARK_GEN) or a MarkDecorator produced by pytest.mark.<name>. Any other type (int, dict, raw Mark, None) is rejected because it cannot be normalized to a marker.","triggerScenarios":"node.add_marker(42); node.add_marker({'name': 'skip'}); node.add_marker(some_mark.mark) passing a raw Mark instead of MarkDecorator; node.add_marker(None).","commonSituations":"Confusing Mark with MarkDecorator; passing a marker instance created via some_mark.args instead of pytest.mark.skip; programmatic marker construction errors.","solutions":["Pass a string marker name: node.add_marker('skip').","Pass a MarkDecorator from the mark generator: node.add_marker(pytest.mark.skip).","If you hold a raw Mark, wrap it: MarkDecorator(mark) before adding."],"exampleFix":"// before\nnode.add_marker(my_mark.mark)\n// after\nfrom _pytest.mark import MarkDecorator\nnode.add_marker(MarkDecorator(my_mark.mark))","handlingStrategy":"type-guard","validationCode":"from _pytest.mark import MarkDecorator\nassert isinstance(marker, (str, MarkDecorator))","typeGuard":"def _is_valid_marker(marker) -> bool:\n    from _pytest.mark import MarkDecorator\n    return isinstance(marker, (str, MarkDecorator))","tryCatchPattern":null,"preventionTips":["Prefer string marker names for add_marker.","Distinguish Mark (raw) from MarkDecorator when constructing programmatically."],"tags":["pytest","nodes","markers","valueerror"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}