phalcon/cphalcon · error · Phalcon\Filter\Exceptions\FilterNotRegistered

Filter {name} is not registered

Error message

Filter {name} is not registered

What it means

Phalcon\Filter\Filter is a lazy locator of sanitizers: get(name) resolves the name against its mapper and instantiates the service once. FilterNotRegistered is thrown when the requested name is not in the mapper — neither a built-in filter (alnum, alpha, bool, email, float, absint, int, lower, upper, striptags, trim, string, url, special, regex, replace, remove, ...) nor a custom one registered via set().

Source

Thrown at phalcon/Filter/Filter.zep:215

        return call_user_func_array([sanitizer, "__invoke"], args);
    }

    /**
     * Get a service. If it is not in the mapper array, create a new object,
     * set it and then return it.
     *
     * @param string $name
     *
     * @return mixed
     * @throws Exception
     */
    public function get(string name) -> var
    {
        var definition;

        if (true !== isset(this->mapper[name])) {
            throw new FilterNotRegistered(name);
        }

        if (true !== isset(this->services[name])) {
            let definition           = this->mapper[name],
                this->services[name] = this->createInstance(definition);
        }

        return this->services[name];
    }

    /**
     * Returns the default sanitizer name to class map. This is the single
     * source for the built-in sanitizer registry: when adding a sanitizer,
     * add its `FILTER_*` constant and its entry here.
     *
     * @return string[]
     */
    public static function getDefaultMapper() -> array

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Check availability first: if (!$filter->has('slugify')) { $filter->set('slugify', SlugFilter::class); }
  2. Fix the name to match a built-in exactly — e.g. 'upper', 'striptags', 'absint'
  3. Register custom sanitizers once at bootstrap on the shared DI 'filter' service so every consumer sees them

Example fix

// before
$value = $filter->sanitize($input, 'slug'); // throws FilterNotRegistered

// after
$filter->set('slug', SlugFilter::class);
$value = $filter->sanitize($input, 'slug');
Defensive patterns

Strategy: validation

Validate before calling

if (!$filter->has('slugify')) {
    $filter->set('slugify', SlugFilter::class);
}
return $filter->get('slugify');

Type guard

function resolveFilter(\Phalcon\Filter\FilterInterface $filter, string $name)
{
    if (!$filter->has($name)) {
        throw new InvalidArgumentException("Unknown filter '{$name}'. Known: " . implode(', ', array_keys($filter->getMapper?.() ?? [])) );
    }
    return $filter->get($name);
}

Try / catch

use Phalcon\Filter\Exceptions\FilterNotRegistered;
try {
    $clean = $filter->sanitize($value, 'slugify');
} catch (FilterNotRegistered $e) {
    // fall back to a known-safe built-in or fail the request input
    $clean = $filter->sanitize($value, 'string');
}

Prevention

When it happens

Trigger: $filter->get('slugify') without first calling $filter->set('slugify', SlugFilter::class); a typo like $filter->get('sanitize') or 'upperCase' (the built-in is 'upper'); custom filters registered on a different Filter instance than the one resolving; the DI 'filter' service rebuilt from the default factory, discarding set() calls made earlier.

Common situations: Custom sanitizers used in Validation::setFilters() or sanitize() whose registration code was removed in a refactor; names written in config (camelCase vs lowercase mismatch); PHP 8 constructor promotion changes dropping the set() bootstrap; tests building new Filter() per case and forgetting re-registration.

Related errors


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