phalcon/cphalcon · error · Phalcon\Mvc\Router\Exceptions\BeforeMatchNotCallable
Before-Match callback is not callable in matched route
Error message
Before-Match callback is not callable in matched route
What it means
During matching, when a static (literal-pattern) route has a beforeMatch callback attached, the router verifies it with is_callable() before invoking it. If the value is set but not callable - a string naming a nonexistent function/method, a malformed array callable, or a class that is not autoloadable at match time - BeforeMatchNotCallable is thrown while handling the request.
Source
Thrown at phalcon/Mvc/Router.zep:1353
let staticHostRegex = staticRoute->getCompiledHostName();
if staticHostRegex !== null {
let staticMatched = preg_match(staticHostRegex, currentHostName);
} else {
let staticMatched = currentHostName == staticHostname;
}
if !staticMatched {
continue;
}
}
let staticBeforeMatch = staticRoute->getBeforeMatch();
if staticBeforeMatch !== null {
if unlikely !is_callable(staticBeforeMatch) {
throw new BeforeMatchNotCallable();
}
let routeFound = {staticBeforeMatch}(handledUri, staticRoute, this);
if !routeFound {
continue;
}
}
let routeFound = true,
matches = null,
parts = staticRoute->getPaths(),
this->matchedRoute = staticRoute;
break;
}
}
}View on GitHub (pinned to b7419de9cd)
Solutions
- Fix the reference so it points at an existing, autoloadable static method: beforeMatch('App\Filters\AdminGate::check')
- Verify with is_callable() at route-definition time (assert once during boot) so bad references fail at startup with your own context
- Regenerate the router cache after renaming/moving any class referenced by beforeMatch callables
- Ensure the autoloader covering the callable's class is active in every process that loads the cached routes (web + CLI)
Example fix
// before
$router->add('/admin', ['controller' => 'admin', 'action' => 'index'])
->beforeMatch('App\Filter\AdminGate::check'); // wrong namespace -> throws at match time
// after: assert at definition time, reference a real method
class AdminGate { public static function check(string $uri, \Phalcon\Mvc\Router\RouteInterface $route): bool { /* ... */ return true; } }
$cb = [AdminGate::class, 'check'];
assert(is_callable($cb));
$router->add('/admin', ['controller' => 'admin', 'action' => 'index'])
->beforeMatch($cb); Defensive patterns
Strategy: validation
Validate before calling
// Assert every beforeMatch is really callable at definition time
foreach ($router->getRoutes() as $route) {
$cb = $route->getBeforeMatch();
if ($cb !== null && !is_callable($cb)) {
throw new LogicException('Route ' . $route->getRouteId() . ' has a non-callable beforeMatch');
}
} Type guard
function isUsableBeforeMatch(mixed $cb): bool
{
return $cb === null || is_callable($cb);
} Try / catch
try {
$router->handle();
} catch (\Phalcon\Mvc\Router\Exceptions\BeforeMatchNotCallable $e) {
// one route's guard references a missing class/method: fail loud, page 500 with context
$logger->critical('beforeMatch not callable: ' . $e->getMessage());
throw $e;
} Prevention
- Reference beforeMatch guards as [ClassName::class, 'method'] so refactorings break at definition time
- Regenerate router caches whenever classes named in route metadata change
- Verify autoload coverage for filter classes in web, CLI, and worker processes
When it happens
Trigger: ->beforeMatch('App\Filters\Gate::check') where Gate::check does not exist (renamed/removed, typo, wrong namespace); array callable ['Filter', 'method'] where the method is not static or is misspelled; loading routes from a cache dump into a process whose autoloader cannot find the filter class (cache built in CLI, matched in web with a different autoload path).
Common situations: Renaming or deleting a filter class without regenerating route caches; typos in callable strings; non-public or instance methods referenced as static callables; composer autoload differences between the dumping environment and the serving environment.
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}')
- Invalid route position
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/9c99cadca5785c93.
Report an issue: GitHub.