phalcon/cphalcon · error · Phalcon\Mvc\View\Engine\Volt\Exceptions\InvalidExtension
The extension is not valid
Error message
The extension is not valid
What it means
Volt\Compiler::addExtension() registers a compiler extension — an object whose methods (compileX, filterX) are invoked during template compilation, optionally via initialize(this). The API requires an object instance, so passing anything else (typically the extension's class-name string) throws InvalidExtension at phalcon/Mvc/View/Engine/Volt/Compiler.zep:185.
Source
Thrown at phalcon/Mvc/View/Engine/Volt/Compiler.zep:185
*
* @param ViewBaseInterface|null view
*/
public function __construct(<ViewBaseInterface> view = null)
{
let this->view = view;
}
/**
* Registers a Volt's extension
*
* @var mixed extension
*
* @return static
*/
public function addExtension(extension) -> <static>
{
if unlikely typeof extension != "object" {
throw new InvalidExtension();
}
/**
* Initialize the extension
*/
if method_exists(extension, "initialize") {
extension->initialize(this);
}
let this->extensions[] = extension;
return this;
}
/**
* Register a new filter in the compiler
*
* @param string nameView on GitHub (pinned to b7419de9cd)
Solutions
- Instantiate: $compiler->addExtension(new \App\Volt\MyExtension())
- When extension names come from config, map them: array_map(fn($c) => new $c(), $config->voltExtensions)
- Ensure the class exists/is autoloadable before instantiation so you get a clearer error otherwise
Example fix
// before $volt->getCompiler()->addExtension(\App\Volt\HashExtension::class); // string // after $volt->getCompiler()->addExtension(new \App\Volt\HashExtension());
Defensive patterns
Strategy: type-guard
Validate before calling
if (!is_object($extension)) {
throw new \InvalidArgumentException('Volt compiler extensions must be object instances');
} Type guard
function isExtensionInstance(mixed $ext): bool
{
return is_object($ext);
} Prevention
- Instantiate extension classes before addExtension()
- Map class-name config to instances: array_map(fn($c) => new $c(), $names)
- Remember: compiler extensions take objects, view engines take closures/strings
When it happens
Trigger: $compiler->addExtension(MyVoltExtension::class) passing the name instead of an instance; passing a string service name from config into addExtension(); passing null when a config-driven extension list has a gap.
Common situations: Confusing Volt compiler extensions with view engines (engines accept service-name strings, compiler extensions do not); config files storing extension class names and being passed through un-instantiated; DI-based setups assuming auto-resolution everywhere.
Understand the failure class
Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.
Related errors
- 'always' must be a bool value
- 'prefix' must be a string
- 'separator' must be a string
- 'extension' must be a string
- Invalid haystack
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/09201a38170a17d7.
Report an issue: GitHub.