phalcon/cphalcon · error · Phalcon\Filter\Validation\Exceptions\InvalidFilterService

Returned 'filter' service is invalid

Error message

Returned 'filter' service is invalid

What it means

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.

Source

Thrown at phalcon/Filter/Validation.zep:208

        let this->data = data;
        this->setEntity(entity);

        // if data is not an array / object, entity is null, or data is empty, then no need to proceed further
        if unlikely (typeof data != "array" && typeof data != "object") || (null === entity) || empty data {
            return this;
        }

        let container = this->getDI();
        if container === null {
            let container = Di::getDefault();

            if container === null {
                throw new FilterServiceUnavailable();
            }
        }
        let filterService = <FilterInterface> container->getShared("filter");
        if unlikely typeof filterService != "object" {
            throw new InvalidFilterService();
        }

        if empty whitelist {
            let whitelist = this->whitelist;
        }

        let filters = this->filters;

        for field, value in data {
            /**
             * Skip numeric (integer) keys; entity setters and properties are
             * always string-named, so camelize() would fail on them. See
             * cphalcon issue #17173.
             */
            if typeof field != "string" {
                continue;
            }

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Fix the service to return an instance: 'filter' => function () { return (new FilterFactory())->newInstance(); }
  2. Return your custom Filter object implementing Phalcon\Filter\FilterInterface
  3. Verify after building the container: assert($di->getShared('filter') instanceof FilterInterface)

Example fix

// before
$di->setShared('filter', function () {
    return \Phalcon\Filter\FilterFactory::class; // string, not an object
});

// after
$di->setShared('filter', function () {
    return (new \Phalcon\Filter\FilterFactory())->newInstance();
});
Defensive patterns

Strategy: type-guard

Validate before calling

$filter = $di->getShared('filter');
if (!is_object($filter)) {
    throw new RuntimeException('DI filter service must return an object, got ' . get_debug_type($filter));
}

Type guard

function assertFilterService($service): \Phalcon\Filter\FilterInterface
{
    if (!$service instanceof \Phalcon\Filter\FilterInterface) {
        throw new RuntimeException('filter service misconfigured: ' . get_debug_type($service));
    }
    return $service;
}

Try / catch

use Phalcon\Filter\Validation\Exceptions\InvalidFilterService;
try {
    $v->bind($entity, $data);
} catch (InvalidFilterService $e) {
    throw new RuntimeException('Fix DI: filter must resolve to FilterInterface instance', 0, $e);
}

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/c728bdf8498dba76. Report an issue: GitHub.