phalcon/cphalcon · error · Phalcon\Cli\Router\Exceptions\InvalidRoutePaths
The route contains invalid paths ('{pattern}')
Error message
The route contains invalid paths ('{pattern}') What it means
When a CLI route's paths define a namespaced task (task name containing a backslash), Phalcon splits it with get_class_ns()/get_ns_class() to derive the namespace and the bare task name. If either half comes back null — the string does not decompose into namespace + class name — InvalidRoutePaths is thrown with the route pattern.
Source
Thrown at phalcon/Cli/Router/Route.zep:460
let routePaths = [];
// Process module name
if moduleName !== null {
let routePaths["module"] = moduleName;
}
// Process task name
if taskName !== null {
// Check if we need to obtain the namespace
if memstr(taskName, "\\") {
// Extract the real class name from the namespaced class
let realClassName = get_class_ns(taskName);
// Extract the namespace from the namespaced class
let namespaceName = get_ns_class(taskName);
if unlikely (namespaceName === null || realClassName === null) {
throw new InvalidRoutePaths(pattern);
}
// Update the namespace
if namespaceName {
let routePaths["namespace"] = namespaceName;
}
} else {
let realClassName = taskName;
}
// Always pass the task to lowercase
let routePaths["task"] = uncamelize(realClassName);
}
// Process action name
if actionName !== null {
let routePaths["action"] = actionName;
}View on GitHub (pinned to b7419de9cd)
Solutions
- Remove leading/trailing backslashes: ['task' => 'App\Tasks\Main']
- Or specify namespace and task separately: ['namespace' => 'App\Tasks', 'task' => 'main']
- Keep task names un-namespaced and pass the namespace under its own 'namespace' path key
Example fix
// before
$router->add('/jobs', ['task' => '\App\Tasks\Main']);
// after
$router->add('/jobs', ['namespace' => 'App\Tasks', 'task' => 'main']); Defensive patterns
Strategy: validation
Validate before calling
function assertValidTaskName(string $task): void
{
if (strpos($task, '\\') !== false &&
!preg_match('/^[A-Za-z_][A-Za-z0-9_]*(\\[A-Za-z_][A-Za-z0-9_]*)+$/', $task)) {
throw new InvalidArgumentException('Malformed namespaced task: ' . $task);
}
}
assertValidTaskName($task);
$router->add('/jobs', ['task' => $task]); Type guard
/**
* A namespaced task must decompose into namespace + class name:
* no leading/trailing backslash, no empty segments.
*/
function isDecomposableTaskName(string $task): bool
{
return preg_match('/^[A-Za-z_][A-Za-z0-9_]*(\\[A-Za-z_][A-Za-z0-9_]*)+$/', $task) === 1;
} Try / catch
try {
$router->add($pattern, $paths);
} catch (\Phalcon\Cli\Router\Route\Exception\InvalidRoutePaths $e) {
// Falls through when namespace/class extraction from the task name fails.
// Split 'App\Tasks\Main' into namespace + task keys and retry.
$parts = explode('\\', trim($paths['task'], '\\'));
$task = array_pop($parts);
$router->add($pattern, ['namespace' => implode('\\', $parts), 'task' => $task]);
} Prevention
- Never put a leading backslash in task names used as route paths
- Prefer separate 'namespace' and 'task' path keys over combined namespaced names
- Validate dynamically built task names with a regex before add()
When it happens
Trigger: $router->add('/jobs', ['task' => '\Tasks\Main']) with a leading backslash, 'App\Tasks\' with a trailing backslash, or a lone '\' — none decompose into a namespace plus a real class name.
Common situations: Copying fully-qualified class names with the leading \ exactly as written in PHP source into route paths; concatenating namespace constants ('NS . '\Tasks\' style) that leave empty segments.
Related errors
- Arguments must be an array or string, {type} given
- Before-Match callback is not callable in matched route '{pat
- Before-Match callback is not callable in matched route '{pat
- Invalid module definition for module '{moduleName}': The mod
- Module definition path '{path}' does not exist
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/21f913f6c8ebbe49.
Report an issue: GitHub.