{"record":{"id":"a10a816abd6afc08","repo":"phalcon/cphalcon","slug":"one-of-the-validators-is-not-valid","errorCode":null,"errorMessage":"One of the validators is not valid","messagePattern":"One of the validators is not valid","errorType":"exception","errorClass":"Phalcon\\Filter\\Validation\\Exceptions\\InvalidValidator","httpStatus":null,"severity":"error","filePath":"phalcon/Filter/Validation.zep","lineNumber":672,"sourceCode":"            // if user provided entity, bind and assign the data to the entity\n            this->bind(entity, inputData, whitelist);\n        }\n\n        /**\n         * Validation classes can implement the 'beforeValidation' callback\n         */\n        if method_exists(this, \"beforeValidation\") {\n            let status = this->{\"beforeValidation\"}(inputData, this->entity, this->messages);\n\n            if status === false {\n                return status;\n            }\n        }\n\n        for field, validators in validatorData {\n            for validator in validators {\n                if unlikely typeof validator != \"object\" {\n                    throw new InvalidValidator();\n                }\n\n                /**\n                 * Call internal validations, if it returns true, then skip the\n                 * current validator\n                 */\n                if this->preChecking(field, validator) {\n                    continue;\n                }\n\n                /**\n                 * Check if the validation must be canceled if this validator fails\n                 */\n                if validator->validate(this, field) === false {\n                    if validator->getOption(\"cancelOnFail\") {\n                        break;\n                    }\n                }","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Filter/Validation.zep#L654-L690","documentation":"During validate(), every registered validator entry must be an object implementing ValidatorInterface (add() enforces this via its type signature, but setValidators(array) does not check inner entries). InvalidValidator is thrown when a per-field validator entry is not an object — typically a class-name string injected through setValidators() or a subclass.","triggerScenarios":"$validation->setValidators(['email' => ['Phalcon\\Filter\\Validation\\Validator\\Email']]) — string class names instead of instances; a subclass building $validators with ['field' => 'SomeValidatorClass']; a config-driven builder mapping YAML validator names straight into the map.","commonSituations":"Defining validators declaratively in config (strings) without instantiating them through Phalcon\\Filter\\Validation\\ValidatorFactory; copying older examples that predates the typed add() signature; caching serialized maps that lost the objects.","solutions":["Instantiate each validator: $validation->setValidators(['email' => [new Email()]])","Or use the fluent API: $validation->add('email', new Email()) — the <ValidatorInterface> parameter catches this at call time","For config-driven rules, resolve names through ValidatorFactory: (new ValidatorFactory())->newInstance('email')"],"exampleFix":"// before\n$validation->setValidators([\n    'email' => ['\\Phalcon\\Filter\\Validation\\Validator\\Email'], // string -> throws\n]);\n\n// after\n$validation->setValidators([\n    'email' => [new \\Phalcon\\Filter\\Validation\\Validator\\Email()],\n]);","handlingStrategy":"type-guard","validationCode":"foreach ($validation->getValidators() as $field => $validators) {\n    foreach ($validators as $v) {\n        if (!is_object($v)) {\n            throw new RuntimeException(sprintf('Validator for %s is %s, expected ValidatorInterface object', $field, get_debug_type($v)));\n        }\n    }\n}\n$validation->validate($data);","typeGuard":"function validatorsAreObjects(\\Phalcon\\Filter\\Validation $validation): bool\n{\n    foreach ($validation->getValidators() as $list) {\n        foreach ($list as $validator) {\n            if (!$validator instanceof \\Phalcon\\Filter\\Validation\\ValidatorInterface) {\n                return false;\n            }\n        }\n    }\n    return true;\n}","tryCatchPattern":"use Phalcon\\Filter\\Validation\\Exceptions\\InvalidValidator;\ntry {\n    $messages = $v->validate($data);\n} catch (InvalidValidator $e) {\n    throw new RuntimeException('Validator map contains non-objects; instantiate validators or use add()', 0, $e);\n}","preventionTips":["Build rule sets with add()/rule() so the ValidatorInterface type is enforced at registration time","Map config strings through ValidatorFactory::newInstance() before injecting","Never inject class-name strings via setValidators()"],"tags":["phalcon","validation","validator","type-error"],"backgroundTag":"invalid-validator-type","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}