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

'separator' must be a string

Error message

'separator' must be a string

What it means

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.

Source

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

            }
        }

        /**
         * There is no compiled separator by default
         */
        if !fetch compiledSeparator, options["separator"] {
            if fetch compiledSeparator, options["compiledSeparator"] {
                trigger_error(
                    "The 'compiledSeparator' option is deprecated. Use 'separator' instead.",
                    E_USER_DEPRECATED
                );
            } else {
                let compiledSeparator = "%%";
            }
        }

        if unlikely typeof compiledSeparator != "string" {
            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");

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Omit 'separator' to accept the '%%' default, or pass an explicit string like '-'
  2. Cast/normalize: 'separator' => (string) $options['separator']
  3. Remove null placeholders from option arrays before setOptions()

Example fix

// before
$volt->setOptions(['separator' => $config->get('voltSeparator')]); // null

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

Strategy: validation

Validate before calling

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

Type guard

function isVoltSeparatorValid(mixed $sep): bool
{
    return !isset($sep) || is_string($sep);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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