phalcon/cphalcon · error · Phalcon\Mvc\Router\Exceptions\InvalidRoutePosition
Invalid route position
Error message
Invalid route position
What it means
Router::attach() only accepts two positions: Router::POSITION_LAST (append) and Router::POSITION_FIRST (prepend). Any other integer hits the default branch and throws InvalidRoutePosition - attach() is not a general-purpose 'insert at index N' API.
Source
Thrown at phalcon/Mvc/Router.zep:672
*
* @param RouteInterface $route
* @param int $position
*
* @return static
*/
public function attach(
<RouteInterface> route,
int position = Router::POSITION_LAST
) -> <static> {
switch position {
case self::POSITION_LAST:
let this->routes[] = route;
break;
case self::POSITION_FIRST:
let this->routes = array_merge([route], this->routes);
break;
default:
throw new InvalidRoutePosition();
}
let this->methodRoutesDirty = true;
return this;
}
/**
* Removes all the pre-defined routes
*/
public function clear() -> void
{
let this->routes = [],
this->methodRoutes = [],
this->candidatesByMethod = [],
this->routeMeta = [],
this->staticByMethod = [],
this->staticShadowedByMethod = [],View on GitHub (pinned to b7419de9cd)
Solutions
- Use only Router::POSITION_LAST or Router::POSITION_FIRST when calling attach()
- If routes must be ordered, attach them in the required order (FIRST for the ones that must win, LAST for the rest) instead of numeric positions
- When positions come from config, whitelist-map them: 'first' => Router::POSITION_FIRST, 'last' => Router::POSITION_LAST, and reject anything else at load time
Example fix
// before $router->attach($route, 2); // throws InvalidRoutePosition // after use Phalcon\Mvc\Router; $router->attach($route, Router::POSITION_FIRST); // or Router::POSITION_LAST // config-driven positions: map and validate $map = ['first' => Router::POSITION_FIRST, 'last' => Router::POSITION_LAST]; $pos = $map[$definition['position'] ?? 'last'] ?? Router::POSITION_LAST; $router->attach($route, $pos);
Defensive patterns
Strategy: validation
Validate before calling
use Phalcon\Mvc\Router;
$allowed = [Router::POSITION_FIRST, Router::POSITION_LAST];
if (!in_array($position, $allowed, true)) {
throw new InvalidArgumentException('position must be Router::POSITION_FIRST or POSITION_LAST');
}
$router->attach($route, $position); Type guard
function isValidAttachPosition(int $position): bool
{
return in_array($position, [\Phalcon\Mvc\Router::POSITION_FIRST, \Phalcon\Mvc\Router::POSITION_LAST], true);
} Try / catch
try {
$router->attach($route, $position);
} catch (\Phalcon\Mvc\Router\Exceptions\InvalidRoutePosition $e) {
$router->attach($route, \Phalcon\Mvc\Router::POSITION_LAST); // safe default
} Prevention
- Map config strings ('first'/'last') to the class constants at load time and reject unknown values
- Never pass computed indices to attach(); order is expressed by FIRST vs LAST plus registration order
- Add unit tests asserting attach() is only ever called with the two constants
When it happens
Trigger: Calling $router->attach($route, 2) or any int other than the two constants; computing a position arithmetically (POSITION_FIRST + 1); passing a config-driven value like 'top'/'1' from a routes config file without mapping it to the constants.
Common situations: Assuming attach() supports arbitrary ordering indices because the signature takes an int; loading route definitions from config where position is a string that must be translated; copying code between router implementations with different position semantics.
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
- The route contains invalid paths ('{pattern}')
- Cannot cache router: route id '{routeId}' has a Closure befo
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/8fc43ad328eb0779.
Report an issue: GitHub.