{"record":{"id":"e1aeb2d5edb253be","repo":"phalcon/cphalcon","slug":"before-match-callback-is-not-callable-in-matched-r-e1aeb2","errorCode":null,"errorMessage":"Before-Match callback is not callable in matched route '{pattern}'","messagePattern":"Before-Match callback is not callable in matched route '(.+?)'","errorType":"exception","errorClass":"Phalcon\\Cli\\Router\\Exceptions\\BeforeMatchNotCallable","httpStatus":null,"severity":"error","filePath":"phalcon/Cli/Router/Route.zep","lineNumber":124,"sourceCode":"     * route id, so resetting the sequence while a router still holds routes\n     * makes newly created routes overwrite existing entries.\n     */\n    public static function reset() -> void\n    {\n        let self::uniqueId = 0;\n    }\n\n    /**\n     * Sets a callback that is called if the route is matched.\n     * The developer can implement any arbitrary conditions here\n     * If the callback returns false the route is treated as not matched\n     *\n     * @param mixed callback\n     */\n    public function beforeMatch(var callback) -> <RouteInterface>\n    {\n        if unlikely !is_callable(callback) {\n            throw new BeforeMatchNotCallable(this->pattern);\n        }\n\n        let this->beforeMatch = callback;\n\n        return this;\n    }\n\n    /**\n     * Replaces placeholders from pattern returning a valid PCRE regular\n     * expression\n     */\n    public function compilePattern( string pattern) -> string\n    {\n        var idPattern;\n        array map;\n\n        // If a pattern contains ':', maybe there are placeholders to replace\n        if memstr(pattern, \":\") {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Cli/Router/Route.zep#L106-L142","documentation":"Route::beforeMatch() validates its argument immediately when the callback is set on a CLI route. It accepts only what is_callable() accepts: a closure, an invokable object, an existing function-name string, or a [object, 'method'] array. Anything else — a bare method-name string, a boolean flag, a config key — throws BeforeMatchNotCallable with the route pattern.","triggerScenarios":"$route->beforeMatch('isAdmin') where no global function isAdmin exists; $route->beforeMatch([$this, 'check']) where the class defines no check() method; $route->beforeMatch('true') used as an on/off switch.","commonSituations":"Passing a method name string instead of the [$object, 'method'] array; typos in function/method names; treating beforeMatch like a boolean option after reading simplified examples.","solutions":["Pass a closure: $route->beforeMatch(function ($args, $route, $router) { return true; })","For methods use the array form [$this, 'check'] or a static callable ['Checker', 'allowed']","For named functions, pass only the name of a function that actually exists"],"exampleFix":"// before\n$route->beforeMatch('checkMaintenance');\n\n// after\n$route->beforeMatch(function ($args, $route, $router) {\n    return !file_exists('/tmp/maintenance.lock');\n});","handlingStrategy":"validation","validationCode":"$callback = function ($args, $route, $router) {\n    return php_sapi_name() === 'cli';\n};\nassert(is_callable($callback)); // trivially true, but guards refactors to arrays/strings\n$route->beforeMatch($callback);","typeGuard":"/**\n * beforeMatch accepts closures, invokable objects, existing function\n * names, and [object, method] arrays — exactly what is_callable allows.\n */\nfunction isBeforeMatchCallback($value): bool\n{\n    return is_callable($value);\n}","tryCatchPattern":"try {\n    $route->beforeMatch($callback);\n} catch (\\Phalcon\\Cli\\Router\\Route\\Exception\\BeforeMatchNotCallable $e) {\n    // Message contains the route pattern; fix the callback reference at the call site\n    throw new LogicException('Invalid beforeMatch for ' . $e->getMessage(), 0, $e);\n}","preventionTips":["Prefer closures for beforeMatch callbacks","For methods, pass the full [$object, 'method'] array — never the method name alone","Static analysis (PHPStan/Psalm level 5+) flags callables that reference unknown functions/methods"],"tags":["phalcon","cli","router","callback","callable"],"backgroundTag":"callback-not-callable","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}