phalcon/cphalcon · error · Phalcon\Mvc\View\Exceptions\ViewsDirItemMustBeString

Views directory item must be a string

Error message

Views directory item must be a string

What it means

When setViewsDir() receives an array, Phalcon iterates it and each element must itself be a string path; a non-string element (null, nested array, int) triggers ViewsDirItemMustBeString at phalcon/Mvc/View.zep:1135. The array form exists to let getViewsDirs()/render check multiple view roots in order (e.g. theme dir + app dir), so every entry must be a usable path.

Source

Thrown at phalcon/Mvc/View.zep:1135

     * Sets the views directory. Depending of your platform,
     * always add a trailing slash or backslash
     */
    public function setViewsDir(var viewsDir) -> <static>
    {
        var position, directory, newViewsDir;

        if typeof viewsDir !== "string" && typeof viewsDir !== "array" {
            throw new InvalidViewsDirType();
        }

        if typeof viewsDir == "string" {
            let this->viewsDirs = this->toDirSeparator(viewsDir);
        } else {
            let newViewsDir = [];

            for position, directory in viewsDir {
                if typeof directory != "string" {
                    throw new ViewsDirItemMustBeString();
                }

                let newViewsDir[position] = this->toDirSeparator(directory);
            }

            let this->viewsDirs = newViewsDir;
        }

        return this;
    }

    /**
     * Starts rendering process enabling the output buffering
     */
    public function start() -> <static>
    {
        ob_start();

View on GitHub (pinned to b7419de9cd)

Solutions

  1. array_filter($dirs, 'is_string') (or filter out nulls) before passing the array
  2. Default optional entries to '' or omit them entirely
  3. Validate each entry with is_string() when building the list dynamically

Example fix

// before
$view->setViewsDir([$config->themePath, $config->fallbackThemePath]); // fallback null

// after
$dirs = array_filter([$config->themePath, $config->fallbackThemePath], 'is_string');
$view->setViewsDir(array_values($dirs));
Defensive patterns

Strategy: validation

Validate before calling

$dirs = array_values(array_filter($dirs, 'is_string'));
if ($dirs === []) {
    throw new \InvalidArgumentException('At least one string views directory is required');
}

Type guard

function isStringList(mixed $list): bool
{
    return is_array($list) && array_reduce($list, fn($ok, $v) => $ok && is_string($v), true);
}

Prevention

When it happens

Trigger: setViewsDir([$themesDir . '/dark', null]) where one slot is an unset variable; setViewsDir(json_decode($json, true)) where a value decoded as int/array; array_merge producing nested arrays.

Common situations: Multi-theme setups assembling directory lists dynamically; config arrays with optional directories that end up null; a views array built from a JSON/YAML source with mixed types.

Related errors


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