{"record":{"id":"348c3e2fd02f522c","repo":"sebastianbergmann/phpunit","slug":"no-builder-found-for-match-builder-identification","errorCode":null,"errorMessage":"No builder found for match builder identification <%s>","messagePattern":"No builder found for match builder identification <(.+?)>","errorType":"exception","errorClass":"MatchBuilderNotFoundException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Runtime/Matcher.php","lineNumber":130,"sourceCode":"     * @throws Exception\n     * @throws ExpectationFailedException\n     * @throws MatchBuilderNotFoundException\n     * @throws MethodNameNotConfiguredException\n     * @throws RuntimeException\n     */\n    public function invoked(Invocation $invocation): mixed\n    {\n        if ($this->methodNameRule === null) {\n            throw new MethodNameNotConfiguredException;\n        }\n\n        if ($this->afterMatchBuilderId !== null) {\n            $matcher = $invocation->object()\n                ->__phpunit_getInvocationHandler()\n                ->lookupMatcher($this->afterMatchBuilderId);\n\n            if ($matcher === null) {\n                throw new MatchBuilderNotFoundException($this->afterMatchBuilderId);\n            }\n        }\n\n        $this->invocationRule->invoked($invocation);\n\n        try {\n            $this->parametersRule?->apply($invocation);\n        } catch (ExpectationFailedException $e) {\n            throw new ExpectationFailedException(\n                sprintf(\n                    \"Expectation for %s failed.\\n%s\",\n                    $this->methodNameRule->failureDescription($this->className),\n                    $e->getMessage(),\n                ),\n                $e->getComparisonFailure(),\n            );\n        }\n","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Runtime/Matcher.php#L112-L148","documentation":"Thrown by Matcher::invoked() when an expectation ordered with ->after($id) fires (its method was actually invoked) but no matcher with that id exists on the same double. The lookup goes through $invocation->object()->__phpunit_getInvocationHandler()->lookupMatcher($id), so the referenced id must have been registered earlier with ->id($id) on the very same mock object.","triggerScenarios":"$mock->expects($this->once())->method('b')->after('first'); where no ->method('a')->id('first') exists; the id was registered on a different mock instance (e.g. after recreating the mock); typo in the id string; the id registration line was deleted while the after() remained.","commonSituations":"Refactoring tests and dropping the ->id() call that anchored the ordering; copying an after()-based expectation into another test that never set the id; using ids across two mocks expecting them to share a registry (each mock has its own InvocationHandler).","solutions":["Add the missing anchor on the same mock: $mock->expects($this->once())->method('a')->id('first').","Fix the id string so it matches exactly (ids are case-sensitive).","If the ordering constraint is obsolete, delete the ->after('...') call.","If the anchor lives on another mock, move both expectations onto one mock or drop the cross-mock ordering (it is not supported)."],"exampleFix":"// before\n$mock->expects($this->once())->method('save')->after('load-step');\n// no matcher registered with id 'load-step'\n\n// after\n$mock->expects($this->once())->method('load')->id('load-step');\n$mock->expects($this->once())->method('save')->after('load-step');","handlingStrategy":"validation","validationCode":"// register the anchor id on the same mock before any after() references it\n$mock->expects($this->once())->method('load')->id('load-step');\n$mock->expects($this->once())->method('save')->after('load-step');","typeGuard":"function afterIdIsRegistered(string $id, object $mock): bool\n{\n    return $mock->__phpunit_getInvocationHandler()->lookupMatcher($id) !== null;\n}","tryCatchPattern":"try {\n    $subject->run($mock);\n} catch (PHPUnit\\Framework\\MockObject\\MatchBuilderNotFoundException $e) {\n    // the after() id has no matching id() — add the anchor expectation\n}","preventionTips":["Always write the ->id() line first, then the ->after() line that references it.","Ids are per-mock-object: never reference an id registered on a different instance.","Delete both halves together when removing ordering constraints."],"tags":["phpunit","mock-object","after","matcher-id","dangling-reference"],"backgroundTag":"unresolved-reference-id","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}