phalcon/cphalcon · error · Phalcon\Mvc\Router\Exceptions\InvalidNotFoundPaths

The not-found paths must be an array or string

Error message

The not-found paths must be an array or string

What it means

Router::notFound() stores the paths returned when nothing matches; it only accepts an array (['controller' => 'errors', 'action' => 'show404']) or a string in 'Controller::action' (optionally 'Module::Controller::action') short syntax. Any other type — including null, integers, booleans, or objects — throws InvalidNotFoundPaths. Note the docblock mentions null, but the implementation rejects it; there is no null-clearing path through this method.

Source

Thrown at phalcon/Mvc/Router.zep:1859

        for route in groupRoutes {
            this->attach(route);
        }

        return this;
    }

    /**
     * Set a group of paths to be returned when none of the defined routes are
     * matched
     *
     * @param array|string|null paths
     *
     * @return static
     */
    public function notFound(var paths) -> <static>
    {
        if unlikely (typeof paths !== "array" && typeof paths !== "string") {
            throw new InvalidNotFoundPaths();
        }

        let this->notFoundPaths = paths;

        return this;
    }

    /**
     * Set whether router must remove the extra slashes in the handled routes
     *
     * @param bool remove
     *
     * @return static
     */
    public function removeExtraSlashes( bool remove) -> <static>
    {
        let this->removeExtraSlashes = remove;

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Pass a paths array: $router->notFound(['controller' => 'errors', 'action' => 'show404']);
  2. Or the short string form: $router->notFound('Errors::show404');
  3. To 'disable' behavior, route to a no-op controller/action instead of passing null
  4. If the value comes from config, decode with json_decode(..., true) and confirm it is an array or string

Example fix

// before
$router->notFound(null);
$router->notFound(404);

// after
$router->notFound(
    ['controller' => 'errors', 'action' => 'show404']
);
Defensive patterns

Strategy: type-guard

Validate before calling

// only pass array or 'Controller::action' strings to notFound()
$notFound = $config['notFound'] ?? null;

if ($notFound !== null && !is_array($notFound) && !is_string($notFound)) {
    throw new InvalidArgumentException(
        'notFound must be an array or Controller::action string, got ' . get_debug_type($notFound)
    );
}

if ($notFound !== null) {
    $router->notFound($notFound);
}

Type guard

function isValidNotFoundPaths(mixed $paths): bool
{
    return is_array($paths) || is_string($paths);
}

Try / catch

try {
    $router->notFound($paths);
} catch (\Phalcon\Mvc\Router\Exceptions\InvalidNotFoundPaths $e) {
    $logger->error('Invalid notFound paths: ' . get_debug_type($paths));
    throw $e;
}

Prevention

When it happens

Trigger: $router->notFound(null) attempting to clear the setting; $router->notFound(404); passing a Config object or stdClass as paths; passing a response object instead of route paths.

Common situations: Trying to unset a previously defined not-found route; passing an HTTP status code; feeding an object because the config was decoded without the associative flag.

Related errors


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