phalcon/cphalcon · error · Phalcon\Mvc\View\Engine\Volt\Exceptions\InvalidOptionType

'extension' must be a string

Error message

'extension' must be a string

What it means

The Volt 'extension' option (deprecated alias 'compiledExtension') sets the file extension appended to compiled templates — default '.php' — and must be a string; any other type throws InvalidOptionType('extension', 'string') at phalcon/Mvc/View/Engine/Volt/Compiler.zep:406. Note this is the compiled-file extension, not the template source extension.

Source

Thrown at phalcon/Mvc/View/Engine/Volt/Compiler.zep:406

            throw new InvalidOptionType("separator", "string");
        }

        /**
         * By default the compile extension is .php
         */
        if !fetch compiledExtension, options["extension"] {
            if fetch compiledExtension, options["compiledExtension"] {
                trigger_error(
                    "The 'compiledExtension' option is deprecated. Use 'extension' instead.",
                    E_USER_DEPRECATED
                );
            } else {
                let compiledExtension = ".php";
            }
        }

        if unlikely typeof compiledExtension != "string" {
            throw new InvalidOptionType("extension", "string");
        }

        /**
         * Stat option assumes the compilation of the file
         */
        if !fetch stat, options["stat"] {
            let stat = true;
        }

        /**
         * Check if there is a compiled path
         */
        if typeof compiledPath == "string" {
            /**
             * Calculate the template realpath's
             */
            if !empty compiledPath {
                /**

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Omit the key to keep the '.php' default, or pass an explicit string including the leading dot
  2. Cast where the value may be numeric/nullable: 'extension' => (string) $value
  3. Sanitize the entire options array (always/prefix/separator/extension/path/stat) in one place before setOptions()

Example fix

// before
$volt->setOptions(['extension' => $config->volt->compiledExtension]); // null

// after
$volt->setOptions(['extension' => (string) $config->path('volt.compiledExtension', '.php')]);
Defensive patterns

Strategy: validation

Validate before calling

if (isset($options['extension']) && !is_string($options['extension'])) {
    $options['extension'] = (string) $options['extension'];
}

Type guard

function isVoltExtensionOptionValid(mixed $ext): bool
{
    return !isset($ext) || is_string($ext);
}

Prevention

When it happens

Trigger: setOptions(['extension' => '.php']) is fine, but setOptions(['extension' => null]) or an array throws; option arrays built from user/config input without normalization; deprecated 'compiledExtension' key with a non-string value after a Phalcon 5 upgrade.

Common situations: Config-driven Volt options where the key exists but is empty/null; mixing up 'extension' (compiled file) with engine-registration keys like '.volt'; JSON/YAML sources yielding non-string scalars.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/b6fed7a5491451da. Report an issue: GitHub.