{"record":{"id":"1fb607cd70645d49","repo":"sebastianbergmann/comparator","slug":"no-suitable-comparator-implementation-found","errorCode":null,"errorMessage":"No suitable Comparator implementation found","messagePattern":"No suitable Comparator implementation found","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Factory.php","lineNumber":115,"sourceCode":"        $this->closureComparisonOccurred = false;\n    }\n\n    public function getComparatorFor(mixed $expected, mixed $actual): Comparator\n    {\n        foreach ($this->customComparators as $comparator) {\n            if ($comparator->accepts($expected, $actual)) {\n                return $comparator;\n            }\n        }\n\n        foreach ($this->defaultComparators as $comparator) {\n            if ($comparator->accepts($expected, $actual)) {\n                return $comparator;\n            }\n        }\n\n        // @codeCoverageIgnoreStart\n        throw new RuntimeException('No suitable Comparator implementation found');\n        // @codeCoverageIgnoreEnd\n    }\n\n    /**\n     * Registers a new comparator.\n     *\n     * This comparator will be returned by getComparatorFor() if its accept() method\n     * returns TRUE for the compared values. It has higher priority than the\n     * existing comparators, meaning that its accept() method will be invoked\n     * before those of the other comparators.\n     */\n    public function register(Comparator $comparator): void\n    {\n        array_unshift($this->customComparators, $comparator);\n\n        $comparator->setFactory($this);\n    }\n","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/sebastianbergmann/comparator/blob/00837a9d227b4e123b0b42a91736960f6b0b3583/src/Factory.php#L97-L133","documentation":"ComparatorFactory::getComparatorFor() iterates its registered comparators and throws this RuntimeException when no comparator's accepts($expected, $actual) returns true. It is a fallback that should be unreachable because the factory registers comparators covering all types, but it fires if the chain cannot handle the value pair.","triggerScenarios":"Calling Factory->getComparatorFor($expected, $actual) with a value pair no registered comparator accepts — typically only possible when all comparators have been removed via unregister()/reset() or when a custom factory instance is built without the default comparators.","commonSituations":"Tests that call unregister() or reset() on the factory and then try to compare values; building a Factory with only custom comparators that don't accept the given types; a custom comparator registered with an overly narrow accepts() shadowing defaults after reset().","solutions":["Call (new Factory)->reset() or ensure the default comparator chain is registered before comparing","Register a custom comparator whose accepts() covers the value pair being compared","Check that test teardown (reset/unregister) is not leaving the factory empty for subsequent comparisons","Use the shared default Factory::getInstance()-style setup instead of a hand-built factory with missing comparators"],"exampleFix":"// before\n$factory = new Factory;\n$factory->unregister(new ObjectComparator); // chain now can't handle objects\n$factory->getComparatorFor($a, $b); // RuntimeException\n// after\n$factory = new Factory;\n$factory->register(new MyCustomComparator);\n$factory->getComparatorFor($a, $b)->assertEquals($a, $b);","handlingStrategy":"try-catch","validationCode":"if (!$factory->getComparatorFor(...)) — instead verify the factory retains defaults: avoid unregister/reset in production paths","typeGuard":null,"tryCatchPattern":"try {\n    $comparator = $factory->getComparatorFor($expected, $actual);\n} catch (\\RuntimeException $e) {\n    // rebuild factory with defaults or fall back to === comparison\n    $comparator = (new Factory)->reset()->getComparatorFor($expected, $actual);\n}","preventionTips":["Never unregister all comparators or call reset() in shared/global factory state","Always register a catch-all custom comparator if you build a factory with only custom comparators","Scope reset()/unregister() to test setup/teardown with try/finally"],"tags":["php","phpunit","factory","internal-error"],"backgroundTag":"internal-invariant-violation","analyzedSha":"00837a9d227b4e123b0b42a91736960f6b0b3583","analyzedAt":"2026-09-15T03:36:55.154Z","contentChangedAt":"2026-09-15T03:36:55.154Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}