{"record":{"id":"e21be9ec33cfe898","repo":"cakephp/cakephp","slug":"a-rule-with-the-name-name-already-exists","errorCode":null,"errorMessage":"A rule with the name `{$name}` already exists","messagePattern":"A rule with the name `(.+?)` already exists","errorType":"exception","errorClass":"CakeException","httpStatus":null,"severity":"error","filePath":"src/Datasource/RulesChecker.php","lineNumber":424,"sourceCode":"        } else {\n            $rule->setOptions($options)->setName($name);\n        }\n\n        return $rule;\n    }\n\n    /**\n     * Checks that a rule with the same name doesn't already exist\n     *\n     * @param string $name The name to check\n     * @param array<\\Cake\\Datasource\\RuleInvoker> $rules The rules array to check\n     * @return void\n     * @throws \\Cake\\Core\\Exception\\CakeException\n     */\n    protected function checkName(string $name, array $rules): void\n    {\n        if (array_key_exists($name, $rules)) {\n            throw new CakeException(\"A rule with the name `{$name}` already exists\");\n        }\n    }\n}\n","sourceCodeStart":406,"sourceCodeEnd":428,"githubUrl":"https://github.com/cakephp/cakephp/blob/1128eba9b09f1946df684811350e26f2cef68fac/src/Datasource/RulesChecker.php#L406-L428","documentation":"RulesChecker lets rules be registered under an optional name so they can be referenced later. checkName() enforces name uniqueness within the rules array; adding a second rule with an existing name throws CakeException to prevent silent overwrite of domain rules.","triggerScenarios":"Calling $rules->add(..., 'uniqueEmail') twice in the same table's buildRules(); buildRules() running more than once (e.g. re-invoked via traits/subclasses) re-adding named rules; two parent classes/traits both adding a rule with the same name.","commonSituations":"Copy-pasting rule registrations between parent/child table classes with identical names; conditional rule-adding logic executed multiple times (e.g. in initialize() called repeatedly in tests); merging rule definitions from config where names collide.","solutions":["Remove the duplicate add call, or give one of the rules a distinct name.","Ensure buildRules() runs exactly once per checker; make registration idempotent.","If re-registration is intentional replacement, remove the old rule first or restructure so buildRules() is idempotent.","Rename colliding rules in traits/base classes to reflect their owner, e.g. 'app.uniqueEmail' vs 'plugin.uniqueEmail'."],"exampleFix":"// before\n$rules->add($rules->isUnique(['email']), 'uniqueEmail');\n$rules->add($rules->validCount('tags'), 'uniqueEmail'); // duplicate name\n// after\n$rules->add($rules->isUnique(['email']), 'uniqueEmail');\n$rules->add($rules->validCount('tags'), 'validTagCount');","handlingStrategy":"try-catch","validationCode":"// in Table::buildRules() — register each named rule exactly once\n$ruleName = 'uniqueEmail';\nif (!isset($registered[$ruleName])) {\n    $rules->add($rules->isUnique(['email']), $ruleName);\n    $registered[$ruleName] = true;\n}","typeGuard":null,"tryCatchPattern":"try {\n    $rules->add($rules->isUnique(['email']), $ruleName);\n} catch (\\Cake\\Core\\Exception\\CakeException $e) {\n    if (!str_contains($e->getMessage(), 'already exists')) {\n        throw $e; // different failure — rethrow\n    }\n    // named rule already registered; skip\n}","preventionTips":["Register each named rule exactly once, in buildRules().","Use owner-prefixed unique names when combining traits/inheritance (e.g. 'plugin.uniqueEmail').","Never invoke buildRules() manually multiple times on the same checker.","Document rule names in one place to avoid copy-paste collisions."],"tags":["cakephp","validation","rules","conflict"],"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"}