{"record":{"id":"8bc888de769557cb","repo":"pytest-dev/pytest","slug":"found-2-or-more-testreports-matching-inamepart-r","errorCode":null,"errorMessage":"found 2 or more testreports matching {inamepart!r}: {values}","messagePattern":"found 2 or more testreports matching (.+?): (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/_pytest/pytester.py","lineNumber":379,"sourceCode":"        when: str | None = None,\n    ) -> CollectReport | TestReport:\n        \"\"\"Return a testreport whose dotted import path matches.\"\"\"\n        values = []\n        for rep in self.getreports(names=names):\n            if not when and rep.when != \"call\" and rep.passed:\n                # setup/teardown passing reports - let's ignore those\n                continue\n            if when and rep.when != when:\n                continue\n            if not inamepart or inamepart in rep.nodeid.split(\"::\"):\n                values.append(rep)\n        if not values:\n            raise ValueError(\n                f\"could not find test report matching {inamepart!r}: \"\n                \"no test reports at all!\"\n            )\n        if len(values) > 1:\n            raise ValueError(\n                f\"found 2 or more testreports matching {inamepart!r}: {values}\"\n            )\n        return values[0]\n\n    @overload\n    def getfailures(\n        self,\n        names: Literal[\"pytest_collectreport\"],\n    ) -> Sequence[CollectReport]: ...\n\n    @overload\n    def getfailures(\n        self,\n        names: Literal[\"pytest_runtest_logreport\"],\n    ) -> Sequence[TestReport]: ...\n\n    @overload\n    def getfailures(","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/pytester.py#L361-L397","documentation":"Thrown by Pytester.matchreport() when more than one captured report matches the given inamepart filter. The method is designed to return a single unambiguous report; multiple matches mean the filter is too broad.","triggerScenarios":"Calling matchreport('test_foo') when several parametrized cases share that node-id prefix (e.g. test_foo[0], test_foo[1]); passing an empty inamepart when multiple tests ran; matching on a class name that contains multiple test methods.","commonSituations":"Parametrized tests where each callspec produces a separate TestReport; running multiple test functions and passing an empty filter expecting one; refactoring that merged test names.","solutions":["Provide a more specific inamepart that uniquely identifies one nodeid segment (include the parametrize id, e.g. 'test_foo[0]').","Use getreports() and filter the list yourself when you genuinely want multiple.","Reduce the test suite being run through pytester so only one matching test exists."],"exampleFix":"// before\nrep = reprec.matchreport(\"test_foo\")\n// after - disambiguate by full parametrize id\nrep = reprec.matchreport(\"test_foo[1-2]\")","handlingStrategy":"validation","validationCode":"matches = [r for r in reprec.getreports() if inamepart in r.nodeid.split('::')]\nif len(matches) > 1:\n    # narrow the filter or use the list directly\n    nodeids = [r.nodeid for r in matches]\n    raise AssertionError(f\"ambiguous: {nodeids}\")","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use getreports() and filter yourself when multiple matches are expected.","Include parametrize ids in inamepart to disambiguate.","Run a minimal subset of tests through pytester."],"tags":["pytester","test-report","nodeid","ambiguity"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}