phalcon/cphalcon · error · Phalcon\Assets\Exceptions\InvalidFilter

The filter is not valid

Error message

The filter is not valid

What it means

While applying a collection's filters the manager requires every entry to be an object implementing Phalcon\Assets\FilterInterface (duck-typed contract with a filter(content) method). A non-object value or a foreign object triggers InvalidFilter, because there is no generic way to invoke an arbitrary value as a filter.

Source

Thrown at phalcon/Assets/Manager.zep:880

     * @throws InvalidFilter
     */
    private function applyFilters(
        string content,
        array filters,
        bool mustFilter = true
    ) -> string {
        var filter;

        if (mustFilter !== true) {
            return content;
        }

        for filter in filters {
            /**
             * Filters must be valid FilterInterface instances
             */
            if unlikely (typeof filter !== "object" || !(filter instanceof FilterInterface)) {
                throw new InvalidFilter();
            }

            /**
             * Calls the method 'filter' which must return a filtered version
             * of the content
             */
            let content = filter->filter(content);
        }

        return content;
    }

    /**
     * Calculates the prefixed path including the version
     *
     * @param Collection $collection
     * @param string     $path
     * @param string     $filePath

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Use the built-in filters: `new \Phalcon\Assets\Filters\Cssmin()` / `new \Phalcon\Assets\Filters\Jsmin()`
  2. Wrap custom logic in a class implementing the interface: `class TrimFilter implements \Phalcon\Assets\FilterInterface { public function filter($content) { ...; return $content; } }`
  3. Audit every addFilter() call site and remove raw strings/closures

Example fix

// before
$collection->addFilter('minify');
// after
$collection->addFilter(new \Phalcon\Assets\Filters\Jsmin());
// or a custom implementation
final class StripCommentsFilter implements \Phalcon\Assets\FilterInterface
{
    public function filter(string $content): string
    {
        return preg_replace('/\/\*.*?\*\//s', '', $content);
    }
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!$filter instanceof \Phalcon\Assets\FilterInterface) {
    throw new InvalidArgumentException('Asset filters must implement FilterInterface');
}
$collection->addFilter($filter);

Type guard

function isValidAssetFilter(mixed $filter): bool
{
    return is_object($filter) && $filter instanceof \Phalcon\Assets\FilterInterface;
}

Try / catch

try {
    echo $assets->outputJs('app');
} catch (\Phalcon\Assets\Exceptions\InvalidFilter $e) {
    $logger->error('Collection contains a non-FilterInterface filter entry: ' . $e->getMessage());
    throw $e;
}

Prevention

When it happens

Trigger: `$collection->addFilter('minify')` (string), `$collection->addFilter(fn($c) => $c)` (closure), or `addFilter(new stdClass())` — then any output/filter operation on the collection.

Common situations: Expecting Phalcon\Filter sanitizer names ('trim', 'lower') to work as asset filters; passing callables the way other libraries accept them; wrapping filter callbacks incorrectly.

Related errors


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