{"record":{"id":"09201a38170a17d7","repo":"phalcon/cphalcon","slug":"the-extension-is-not-valid","errorCode":null,"errorMessage":"The extension is not valid","messagePattern":"The extension is not valid","errorType":"exception","errorClass":"Phalcon\\Mvc\\View\\Engine\\Volt\\Exceptions\\InvalidExtension","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/View/Engine/Volt/Compiler.zep","lineNumber":185,"sourceCode":"     *\n     * @param ViewBaseInterface|null view\n     */\n    public function __construct(<ViewBaseInterface> view = null)\n    {\n        let this->view = view;\n    }\n\n    /**\n     * Registers a Volt's extension\n     *\n     * @var mixed extension\n     *\n     * @return static\n     */\n    public function addExtension(extension) -> <static>\n    {\n        if unlikely typeof extension != \"object\" {\n            throw new InvalidExtension();\n        }\n\n        /**\n         * Initialize the extension\n         */\n        if method_exists(extension, \"initialize\") {\n            extension->initialize(this);\n        }\n\n        let this->extensions[] = extension;\n\n        return this;\n    }\n\n    /**\n     * Register a new filter in the compiler\n     *\n     * @param string name","sourceCodeStart":167,"sourceCodeEnd":203,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/View/Engine/Volt/Compiler.zep#L167-L203","documentation":"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.","triggerScenarios":"$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.","commonSituations":"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.","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"],"exampleFix":"// before\n$volt->getCompiler()->addExtension(\\App\\Volt\\HashExtension::class); // string\n\n// after\n$volt->getCompiler()->addExtension(new \\App\\Volt\\HashExtension());","handlingStrategy":"type-guard","validationCode":"if (!is_object($extension)) {\n    throw new \\InvalidArgumentException('Volt compiler extensions must be object instances');\n}","typeGuard":"function isExtensionInstance(mixed $ext): bool\n{\n    return is_object($ext);\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["phalcon","volt","compiler","extensions","type-validation"],"backgroundTag":"invalid-argument-type","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}