{"record":{"id":"410c345b2b85417b","repo":"phalcon/cphalcon","slug":"always-must-be-a-bool-value","errorCode":null,"errorMessage":"'always' must be a bool value","messagePattern":"'always' must be a bool value","errorType":"exception","errorClass":"Phalcon\\Mvc\\View\\Engine\\Volt\\Exceptions\\InvalidOptionType","httpStatus":null,"severity":"error","filePath":"phalcon/Mvc/View/Engine/Volt/Compiler.zep","lineNumber":344,"sourceCode":"\n        let options = this->options;\n\n        /**\n         * This makes that templates will be compiled always\n         */\n        if !fetch compileAlways, options[\"always\"] {\n            if fetch compileAlways, options[\"compileAlways\"] {\n                trigger_error(\n                    \"The 'compileAlways' option is deprecated. Use 'always' instead.\",\n                    E_USER_DEPRECATED\n                );\n            } else {\n                let compileAlways = false;\n            }\n        }\n\n        if unlikely typeof compileAlways != \"boolean\" {\n            throw new InvalidOptionType(\"always\", \"bool value\");\n        }\n\n        /**\n         * Prefix is prepended to the template name\n         */\n        if !fetch prefix, options[\"prefix\"] {\n            let prefix = \"\";\n        }\n\n        if unlikely typeof prefix != \"string\" {\n            throw new InvalidOptionType(\"prefix\", \"string\");\n        }\n\n        /**\n         * Compiled path is a directory where the compiled templates will be\n         * located\n         */\n        if !fetch compiledPath, options[\"path\"] {","sourceCodeStart":326,"sourceCodeEnd":362,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Mvc/View/Engine/Volt/Compiler.zep#L326-L362","documentation":"When parsing Volt compiler options, the 'always' key (or deprecated 'compileAlways') must be a real boolean; anything else triggers InvalidOptionType('always', 'bool value') at phalcon/Mvc/View/Engine/Volt/Compiler.zep:344. This flag forces recompilation of every template on each request — a development-only setting — and a truthy-looking string would silently change compile semantics, hence the strict check.","triggerScenarios":"setOptions(['always' => 'true']) or ['always' => '1'] from env vars/JSON/INI config where everything is a string; ['compileAlways' => 1] using the deprecated key with an int; YAML config parsed with string scalars.","commonSituations":"Reading APP_DEBUG-style env vars into Volt options without casting; Phalcon 4 -> 5 migrations where the old 'compileAlways' spelling now also gets type-checked; config shared across environments with string booleans.","solutions":["Cast before passing: 'always' => (bool) env('VOLT_COMPILE_ALWAYS', false)","Use proper native booleans in the config source (true/false in PHP config, not 'true'/'false')","Rename the deprecated 'compileAlways' key to 'always' at the same time to remove the deprecation notice"],"exampleFix":"// before\n$volt->setOptions(['always' => getenv('APP_DEBUG')]); // '1' string\n\n// after\n$volt->setOptions(['always' => (bool) getenv('APP_DEBUG')]);","handlingStrategy":"validation","validationCode":"$options['always'] = (bool) ($options['always'] ?? $options['compileAlways'] ?? false);\nunset($options['compileAlways']);","typeGuard":"function isVoltOptionsShape(array $options): bool\n{\n    return !isset($options['always'], $options['compileAlways'])\n        || is_bool($options['always'] ?? $options['compileAlways']);\n}","tryCatchPattern":null,"preventionTips":["Cast env/config-sourced booleans: (bool)","Use native true/false in config sources","Rename 'compileAlways' to 'always' during Phalcon 5 upgrades"],"tags":["phalcon","volt","compiler","options","type-validation","env-vars"],"backgroundTag":"config-type-mismatch","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}