{"record":{"id":"c728bdf8498dba76","repo":"phalcon/cphalcon","slug":"returned-filter-service-is-invalid","errorCode":null,"errorMessage":"Returned 'filter' service is invalid","messagePattern":"Returned 'filter' service is invalid","errorType":"exception","errorClass":"Phalcon\\Filter\\Validation\\Exceptions\\InvalidFilterService","httpStatus":null,"severity":"error","filePath":"phalcon/Filter/Validation.zep","lineNumber":208,"sourceCode":"        let this->data = data;\n        this->setEntity(entity);\n\n        // if data is not an array / object, entity is null, or data is empty, then no need to proceed further\n        if unlikely (typeof data != \"array\" && typeof data != \"object\") || (null === entity) || empty data {\n            return this;\n        }\n\n        let container = this->getDI();\n        if container === null {\n            let container = Di::getDefault();\n\n            if container === null {\n                throw new FilterServiceUnavailable();\n            }\n        }\n        let filterService = <FilterInterface> container->getShared(\"filter\");\n        if unlikely typeof filterService != \"object\" {\n            throw new InvalidFilterService();\n        }\n\n        if empty whitelist {\n            let whitelist = this->whitelist;\n        }\n\n        let filters = this->filters;\n\n        for field, value in data {\n            /**\n             * Skip numeric (integer) keys; entity setters and properties are\n             * always string-named, so camelize() would fail on them. See\n             * cphalcon issue #17173.\n             */\n            if typeof field != \"string\" {\n                continue;\n            }\n","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Filter/Validation.zep#L190-L226","documentation":"After obtaining a container, bind() resolves container->getShared('filter') and expects an object implementing FilterInterface. InvalidFilterService is thrown when the service resolves but is not an object — typically a misconfigured DI definition that returns a string (a class name), array, or scalar instead of a filter instance.","triggerScenarios":"A DI closure registered as 'filter' => fn () => FilterFactory::class returning the class name string; a shared service overwritten elsewhere with a non-object; definitions imported from config that map 'filter' to a string class without instantiation.","commonSituations":"Hand-written DI closures that forget ->newInstance(); copying the 'filter' registration from docs but dropping the parentheses; overriding the service in an environment-specific config file with a plain class name.","solutions":["Fix the service to return an instance: 'filter' => function () { return (new FilterFactory())->newInstance(); }","Return your custom Filter object implementing Phalcon\\Filter\\FilterInterface","Verify after building the container: assert($di->getShared('filter') instanceof FilterInterface)"],"exampleFix":"// before\n$di->setShared('filter', function () {\n    return \\Phalcon\\Filter\\FilterFactory::class; // string, not an object\n});\n\n// after\n$di->setShared('filter', function () {\n    return (new \\Phalcon\\Filter\\FilterFactory())->newInstance();\n});","handlingStrategy":"type-guard","validationCode":"$filter = $di->getShared('filter');\nif (!is_object($filter)) {\n    throw new RuntimeException('DI filter service must return an object, got ' . get_debug_type($filter));\n}","typeGuard":"function assertFilterService($service): \\Phalcon\\Filter\\FilterInterface\n{\n    if (!$service instanceof \\Phalcon\\Filter\\FilterInterface) {\n        throw new RuntimeException('filter service misconfigured: ' . get_debug_type($service));\n    }\n    return $service;\n}","tryCatchPattern":"use Phalcon\\Filter\\Validation\\Exceptions\\InvalidFilterService;\ntry {\n    $v->bind($entity, $data);\n} catch (InvalidFilterService $e) {\n    throw new RuntimeException('Fix DI: filter must resolve to FilterInterface instance', 0, $e);\n}","preventionTips":["Register the filter service as a closure that returns (new FilterFactory())->newInstance()","Add a container smoke test: getShared('filter') instanceof FilterInterface after bootstrap"],"tags":["phalcon","validation","dependency-injection","filter","service-configuration"],"backgroundTag":"invalid-service-definition","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}