{"record":{"id":"126efe933f351d42","repo":"cakephp/cakephp","slug":"s-contains-duplicate-method-s-which-is-already-provided-by-s","errorCode":null,"errorMessage":"`%s` contains duplicate method `%s` which is already provided by `%s`.","messagePattern":"`(.+?)` contains duplicate method `(.+?)` which is already provided by `(.+?)`\\.","errorType":"exception","errorClass":"LogicException","httpStatus":null,"severity":"error","filePath":"src/ORM/BehaviorRegistry.php","lineNumber":202,"sourceCode":"                    $class,\n                    $finder,\n                    $duplicate[0],\n                );\n                throw new LogicException($error);\n            }\n            $finders[$finder] = [$alias, $methodName];\n        }\n\n        foreach ($methods as $method => $methodName) {\n            if (isset($this->_methodMap[$method]) && $this->has($this->_methodMap[$method][0])) {\n                $duplicate = $this->_methodMap[$method];\n                $error = sprintf(\n                    '`%s` contains duplicate method `%s` which is already provided by `%s`.',\n                    $class,\n                    $method,\n                    $duplicate[0],\n                );\n                throw new LogicException($error);\n            }\n            $methods[$method] = [$alias, $methodName];\n        }\n\n        return compact('methods', 'finders');\n    }\n\n    /**\n     * Set an object directly into the registry by name.\n     *\n     * @param string $name The name of the object to set in the registry.\n     * @param \\Cake\\ORM\\Behavior $object instance to store in the registry\n     * @return $this\n     */\n    public function set(string $name, object $object)\n    {\n        parent::set($name, $object);\n","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/cakephp/cakephp/blob/1128eba9b09f1946df684811350e26f2cef68fac/src/ORM/BehaviorRegistry.php#L184-L220","documentation":"BehaviorRegistry::_getMethods() throws this LogicException when a newly loaded behavior exposes a public method (proxyable via the table) whose name is already provided by another loaded behavior. CakePHP maps behavior methods onto the table, so duplicate names would be ambiguous and registration is aborted.","triggerScenarios":"$table->addBehavior('SecondBehavior') where SecondBehavior declares a public method like `slugify()` or `softDelete()` that an already-attached behavior also declares; occurs via set() or _create during initialize(), so the table cannot even be constructed.","commonSituations":"Two utility plugins both adding `touch()`/`moveUp()` style methods; loading both a deprecated behavior and its replacement that kept the same API; a project base AppBehavior and a plugin behavior both defining helpers with common names.","solutions":["Remove one of the colliding behaviors from initialize() — the message names which class already provides the method.","Rename the method in the offending behavior (only your own code) to a unique name.","If overriding intentionally, subclass the provider behavior and load only the subclass.","Check for accidental double-loading of the same behavior under two aliases (each alias counts as a provider).","Pin plugin versions or patch vendor behavior so method names stay distinct; file an upstream rename issue."],"exampleFix":"// before\n$this->addBehavior('My.Utils');   // public function touch()\n$this->addBehavior('Shadow.Shadow'); // also public function touch()\n// after\n$this->addBehavior('My.Utils');\n// remove Shadow, or rename its method in a subclass:\nclass MyShadowBehavior extends ShadowBehavior { public function shadowTouch() { return $this->touch(...func_get_args()); } }","handlingStrategy":"try-catch","validationCode":"$newMethods = array_filter(get_class_methods(new SecondBehavior()), fn($m) => !str_starts_with($m, 'find'));\nforeach ($table->behaviors()->loaded() as $loaded) {\n    $overlap = array_intersect($newMethods, get_class_methods($loaded));\n    if ($overlap) { /* handle collision before addBehavior */ }\n}","typeGuard":null,"tryCatchPattern":"try {\n    $table->addBehavior('Shadow.Shadow');\n} catch (\\LogicException $e) {\n    if (str_contains($e->getMessage(), 'duplicate method')) {\n        $this->log($e->getMessage());\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Prefix public methods in reusable behaviors with a plugin-specific word","Never load a behavior and its deprecated/renamed successor together on one table","Grep for public function definitions when introducing a new behavior","Table-level integration tests that instantiate all tables catch this at boot","Check vendor behavior classes for shared helper names like touch/slug before combining plugins"],"tags":["orm","duplicate-method","behavior-conflict","cakephp"],"backgroundTag":"conflicting-config-options","analyzedSha":"1128eba9b09f1946df684811350e26f2cef68fac","analyzedAt":"2026-09-12T12:07:00.388Z","contentChangedAt":"2026-09-12T12:07:00.388Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}