{"record":{"id":"b2a88f268add8b4e","repo":"phalcon/cphalcon","slug":"separator-must-be-a-string","errorCode":null,"errorMessage":"'separator' must be a string","messagePattern":"'separator' must be a string","errorType":"exception","errorClass":"Phalcon\\Mvc\\View\\Engine\\Volt\\Exceptions\\InvalidOptionType","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/View/Engine/Volt/Compiler.zep","lineNumber":388,"sourceCode":"            }\n        }\n\n        /**\n         * There is no compiled separator by default\n         */\n        if !fetch compiledSeparator, options[\"separator\"] {\n            if fetch compiledSeparator, options[\"compiledSeparator\"] {\n                trigger_error(\n                    \"The 'compiledSeparator' option is deprecated. Use 'separator' instead.\",\n                    E_USER_DEPRECATED\n                );\n            } else {\n                let compiledSeparator = \"%%\";\n            }\n        }\n\n        if unlikely typeof compiledSeparator != \"string\" {\n            throw new InvalidOptionType(\"separator\", \"string\");\n        }\n\n        /**\n         * By default the compile extension is .php\n         */\n        if !fetch compiledExtension, options[\"extension\"] {\n            if fetch compiledExtension, options[\"compiledExtension\"] {\n                trigger_error(\n                    \"The 'compiledExtension' option is deprecated. Use 'extension' instead.\",\n                    E_USER_DEPRECATED\n                );\n            } else {\n                let compiledExtension = \".php\";\n            }\n        }\n\n        if unlikely typeof compiledExtension != \"string\" {\n            throw new InvalidOptionType(\"extension\", \"string\");","sourceCodeStart":370,"sourceCodeEnd":406,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/View/Engine/Volt/Compiler.zep#L370-L406","documentation":"The Volt 'separator' option (deprecated alias 'compiledSeparator') is the string glue used to build compiled filenames — template path segments are joined with it, defaulting to '%%' — and must be a string; otherwise InvalidOptionType('separator', 'string') is thrown at phalcon/Mvc/View/Engine/Volt/Compiler.zep:388. Because the separator becomes part of filenames, only string values make sense.","triggerScenarios":"setOptions(['separator' => null]); ['separator' => false]; options arrays assembled dynamically where the key ends up with a non-string value; using the old 'compiledSeparator' key with a wrong type after upgrade.","commonSituations":"Copy-pasted option arrays from blog posts with null placeholders; refactoring config so 'separator' now reads from an undefined key; JSON round-trips turning values into non-strings.","solutions":["Omit 'separator' to accept the '%%' default, or pass an explicit string like '-'","Cast/normalize: 'separator' => (string) $options['separator']","Remove null placeholders from option arrays before setOptions()"],"exampleFix":"// before\n$volt->setOptions(['separator' => $config->get('voltSeparator')]); // null\n\n// after\n$volt->setOptions(['separator' => (string) $config->path('volt.separator', '-')]);","handlingStrategy":"validation","validationCode":"if (isset($options['separator']) && !is_string($options['separator'])) {\n    $options['separator'] = (string) $options['separator'];\n}","typeGuard":"function isVoltSeparatorValid(mixed $sep): bool\n{\n    return !isset($sep) || is_string($sep);\n}","tryCatchPattern":null,"preventionTips":["Omit 'separator' unless you need custom compiled filenames","Strip null placeholders from options arrays","Keep Volt options construction in one tested place"],"tags":["phalcon","volt","compiler","options","type-validation"],"backgroundTag":"config-type-mismatch","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}