{"record":{"id":"b5947c2d115bf265","repo":"phalcon/cphalcon","slug":"the-unique-compilation-prefix-is-invalid","errorCode":null,"errorMessage":"The unique compilation prefix is invalid","messagePattern":"The unique compilation prefix is invalid","errorType":"exception","errorClass":"InvalidCompilationPrefix","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/View/Engine/Volt/Compiler.zep","lineNumber":2137,"sourceCode":"            let this->prefix = unique_path_key(this->currentPath);\n        }\n\n        /**\n         * The user could use a closure generator\n         */\n        if typeof this->prefix == \"object\" {\n            if this->prefix instanceof Closure {\n                let this->prefix = call_user_func_array(\n                    this->prefix,\n                    [\n                        this\n                    ]\n                );\n            }\n        }\n\n        if unlikely typeof this->prefix != \"string\" {\n            throw new InvalidCompilationPrefix();\n        }\n\n        return this->prefix;\n    }\n\n\n    /**\n     * Parses a Volt template returning its intermediate representation\n     *\n     *```php\n     * print_r(\n     *     $compiler->parse(\"{{ 3 + 2 }}\")\n     * );\n     *```\n     *\n     * @param string viewCode\n     *\n     * @return array","sourceCodeStart":2119,"sourceCodeEnd":2155,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/View/Engine/Volt/Compiler.zep#L2119-L2155","documentation":"Volt's compilation prefix (prepended to compiled template keys/names, e.g. for compiled-file naming) is set with Compiler::setPrefix() and may be a string or a Closure receiving the compiler. At compile time Compiler.zep:2137 resolves that Closure and then requires the final value to be a string. If the prefix is neither a string nor a Closure returning one (integer, null, array), the 'Invalid compilation prefix' exception is thrown before any template is compiled.","triggerScenarios":"$compiler->setPrefix(123), setPrefix(null), or setPrefix(function ($compiler) { return null; }) (a Closure with a code path that forgets to return), followed by any compile()/render() call.","commonSituations":"Code written for a dynamic per-application prefix whose Closure returns void on an early-exit branch. Prefixes read from config/env (e.g. getenv() returning false, or a missing config key yielding null) and passed to setPrefix unvalidated. Upgrading code that previously stored the prefix untyped.","solutions":["Make the Closure always return a string: setPrefix(function ($compiler) { return 'myapp'; })","If the prefix comes from config, default it before assigning: $compiler->setPrefix($config->path('volt.prefix', 'default'))","Pass a plain string literal if no dynamism is needed","Add a return-type check in the Closure before returning"],"exampleFix":"// before\n$compiler->setPrefix(function ($compiler) {\n    if ($this->tenant) {\n        return $this->tenant;\n    }\n});\n\n// after\n$compiler->setPrefix(function ($compiler) {\n    return $this->tenant ?: 'default';\n});","handlingStrategy":"validation","validationCode":"if (!$prefix instanceof \\Closure && !is_string($prefix)) {\n    throw new \\InvalidArgumentException(\n        'Volt prefix must be a string or a Closure returning a string'\n    );\n}\nif ($prefix instanceof \\Closure) {\n    $result = $prefix($compiler);\n    if (!is_string($result)) {\n        throw new \\InvalidArgumentException(\n            'Volt prefix Closure must return a string, got ' . gettype($result)\n        );\n    }\n}\n$compiler->setPrefix($prefix);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer a plain string prefix unless you truly need dynamism","Give prefix Closures an explicit return type: function ($compiler): string { ... } so PHP itself enforces the contract","When the prefix comes from config, validate it at boot, not at first render"],"tags":["phalcon","volt","compiler-options","prefix","configuration"],"backgroundTag":"invalid-configuration-value","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}