cakephp/cakephp · error · CakeException

A rule with the name

Error message

A rule with the name `{$name}` already exists

What it means

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.

Solutions

  1. Remove the duplicate add call, or give one of the rules a distinct name.
  2. Ensure buildRules() runs exactly once per checker; make registration idempotent.
  3. If re-registration is intentional replacement, remove the old rule first or restructure so buildRules() is idempotent.
  4. Rename colliding rules in traits/base classes to reflect their owner, e.g. 'app.uniqueEmail' vs 'plugin.uniqueEmail'.

Example fix

// before
$rules->add($rules->isUnique(['email']), 'uniqueEmail');
$rules->add($rules->validCount('tags'), 'uniqueEmail'); // duplicate name
// after
$rules->add($rules->isUnique(['email']), 'uniqueEmail');
$rules->add($rules->validCount('tags'), 'validTagCount');
Defensive patterns

Strategy: try-catch

Validate before calling

// in Table::buildRules() — register each named rule exactly once
$ruleName = 'uniqueEmail';
if (!isset($registered[$ruleName])) {
    $rules->add($rules->isUnique(['email']), $ruleName);
    $registered[$ruleName] = true;
}

Try / catch

try {
    $rules->add($rules->isUnique(['email']), $ruleName);
} catch (\Cake\Core\Exception\CakeException $e) {
    if (!str_contains($e->getMessage(), 'already exists')) {
        throw $e; // different failure — rethrow
    }
    // named rule already registered; skip
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of cakephp/cakephp@1128eba9b0 (2026-09-12). Data as JSON: /api/errors/e21be9ec33cfe898. Report an issue: GitHub.

Appendix: source

Thrown at src/Datasource/RulesChecker.php:424

        } else {
            $rule->setOptions($options)->setName($name);
        }

        return $rule;
    }

    /**
     * Checks that a rule with the same name doesn't already exist
     *
     * @param string $name The name to check
     * @param array<\Cake\Datasource\RuleInvoker> $rules The rules array to check
     * @return void
     * @throws \Cake\Core\Exception\CakeException
     */
    protected function checkName(string $name, array $rules): void
    {
        if (array_key_exists($name, $rules)) {
            throw new CakeException("A rule with the name `{$name}` already exists");
        }
    }
}

View on GitHub (pinned to 1128eba9b0)