phalcon/cphalcon · error · Phalcon\Mvc\Router\Exceptions\GroupRoutesMustBeArray
Group 'routes' must be an array
Error message
Group 'routes' must be an array
What it means
For each entry under config['groups'] (processed by mountGroupFromConfig), the optional inner 'routes' key must be an array of route definitions. A missing key defaults to an empty list, but if the key is present with a non-array value (object, string, scalar), GroupRoutesMustBeArray is thrown.
Source
Thrown at phalcon/Mvc/Router.zep:2141
let paths = groupData["paths"];
}
let group = new Group(paths);
if isset groupData["prefix"] {
group->setPrefix((string) groupData["prefix"]);
}
if isset groupData["hostname"] {
group->setHostname((string) groupData["hostname"]);
}
if !fetch routes, groupData["routes"] {
let routes = [];
}
if typeof routes !== "array" {
throw new GroupRoutesMustBeArray();
}
for routeData in routes {
if !fetch pattern, routeData["pattern"] {
throw new MissingGroupRouteKey("pattern");
}
if !fetch routePaths, routeData["paths"] {
throw new MissingGroupRouteKey("paths");
}
let method = "";
if isset routeData["method"] && routeData["method"] !== null {
let method = strtolower((string) routeData["method"]);
}
switch method {
case "":
case "connect":View on GitHub (pinned to b7419de9cd)
Solutions
- Make group 'routes' a list: "groups": [{"prefix": "/admin", "routes": [{"pattern": ..., "paths": ...}]}]
- Decode config with json_decode($json, true) so nested objects become arrays
- Pre-validate group entries before loadFromConfig
Example fix
// before
{
"groups": [
{
"prefix": "/admin",
"routes": {
"pattern": "/dashboard",
"paths": {"controller": "dashboard"}
}
}
]
}
// after
{
"groups": [
{
"prefix": "/admin",
"routes": [
{
"pattern": "/dashboard",
"paths": {"controller": "dashboard"}
}
]
}
]
} Defensive patterns
Strategy: validation
Validate before calling
// validate group structure: each group is a map; its 'routes' (if present) is a list
foreach ($config['groups'] ?? [] as $i => $group) {
if (!is_array($group)) {
throw new InvalidArgumentException("groups[$i] must be an array");
}
if (isset($group['routes']) && !is_array($group['routes'])) {
throw new InvalidArgumentException("groups[$i]['routes'] must be an array");
}
}
$router->loadFromConfig($config); Type guard
function groupRoutesAreValid(mixed $group): bool
{
return is_array($group)
&& (!isset($group['routes']) || is_array($group['routes']));
} Try / catch
try {
$router->loadFromConfig($config);
} catch (\Phalcon\Mvc\Router\Exceptions\GroupRoutesMustBeArray $e) {
$logger->error('Group config rejected: ' . $e->getMessage());
throw $e;
} Prevention
- A group's 'routes' is a list of entries — never a single object or string
- Omit 'routes' entirely for prefix-only shells (it defaults to empty)
- Always decode route JSON/YAML to associative arrays
When it happens
Trigger: JSON group object where "routes": {...} decodes to stdClass (json_decode without true); a group with "routes": "see other file"; single route object instead of a list under a group.
Common situations: Non-associative json_decode of the whole config (outer arrays survive only if wrapped in []); manual YAML authoring nesting an object where a list is required; config merging that replaced the list.
Related errors
- 'groups' must be an array
- Group route entry is missing 'pattern'
- Group route entry is missing 'paths'
- loadFromConfig requires an array or Phalcon\Config\ConfigInt
- 'defaults' must be an array
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/43c0bff4d23a91d0.
Report an issue: GitHub.