{"record":{"id":"b3939b39256ed041","repo":"cakephp/cakephp","slug":"a-named-route-was-found-for-s-but-matching-failed-passed","errorCode":null,"errorMessage":"A named route was found for `%s`, but matching failed. Passed parameters: `%s`.","messagePattern":"A named route was found for `(.+?)`, but matching failed\\. Passed parameters: `(.+?)`\\.","errorType":"exception","errorClass":"MissingRouteException","httpStatus":404,"severity":"error","filePath":"src/Routing/RouteCollection.php","lineNumber":298,"sourceCode":"    public function match(array $url, array $context): string\n    {\n        // Named routes support optimization.\n        if (isset($url['_name'])) {\n            $name = $url['_name'];\n            unset($url['_name']);\n            if (isset($this->_named[$name])) {\n                $route = $this->_named[$name];\n                $out = $route->match($url + $route->defaults, $context);\n                if ($out) {\n                    return $out;\n                }\n                $message = sprintf(\n                    'A named route was found for `%s`, but matching failed. Passed parameters: `%s`.',\n                    $name,\n                    (string)json_encode($url),\n                );\n\n                throw new MissingRouteException([\n                    'url' => $name,\n                    'context' => $context,\n                    // Escape `%` so the message survives CakeException's vsprintf() pass unchanged.\n                    'message' => str_replace('%', '%%', $message),\n                ]);\n            }\n            throw new MissingRouteException(['url' => $name, 'context' => $context]);\n        }\n\n        foreach ($this->_getNames($url) as $name) {\n            if (empty($this->_routeTable[$name])) {\n                continue;\n            }\n            foreach ($this->_routeTable[$name] as $route) {\n                $match = $route->match($url, $context);\n                if ($match) {\n                    return $match === '/' ? $match : trim($match, '/');\n                }","sourceCodeStart":280,"sourceCodeEnd":316,"githubUrl":"https://github.com/cakephp/cakephp/blob/1128eba9b09f1946df684811350e26f2cef68fac/src/Routing/RouteCollection.php#L280-L316","documentation":"RouteCollection::match() found a route registered with the given `_name`, but Route::match() could not produce a URL from the passed parameters — the parameters don't satisfy the route's template placeholders, defaults, or passed-argument pattern. Cake throws MissingRouteException because URL generation failed even though the route name exists.","triggerScenarios":"Calling Router::url(['_name' => 'route:name', ...]) (which ends up in RouteCollection::match) with parameters that don't match the named route's template: missing a required placeholder value, wrong key names, extra/insufficient passed arguments, or a value that fails the route's regex/pattern constraints.","commonSituations":"Renaming or reshaping a route template in routes.php without updating every Router::url() call referencing it by _name; typos in parameter keys; passing plugin/prefix keys to a route defined without them; a pattern constraint (e.g. [['id', '\\d+']]) rejecting a non-numeric id like a string slug; test code (e.g. testPluginRoutes) generating URLs with stale parameters.","solutions":["Print the route template (Router::getRouteCollection()->get($name)->template and its defaults/patterns) and compare against the exact parameters passed in the failing Router::url()/match() call","Supply every required placeholder in the URL array and remove keys the route template does not use (plugin/prefix/controller/action are ignored for named routes)","Check route pattern constraints — e.g. an id pattern of \\d+ fails for string identifiers; relax the pattern or pass a valid value","If the route shape changed, update the _name reference or connect a new route with that name and the expected parameters","Catch MissingRouteException around URL generation if the link is optional and can be skipped"],"exampleFix":"// before\n$url = Router::url(['_name' => 'articles:view', 'slug' => $article->slug]);\n// route: /articles/view/:id with [['id', '\\d+')]\n\n// after\n$url = Router::url(['_name' => 'articles:view', 'id' => $article->id]);","handlingStrategy":"try-catch","validationCode":"$collection = Router::getRouteCollection();\n$route = $collection->get($name);\nif ($route === null) {\n    throw new RuntimeException(\"Named route {$name} is not connected\");\n}\nforeach ($route->options ?? [] as $key => $pattern) {\n    if (isset($url[$key]) && !preg_match('/^' . $pattern . '$/', (string)$url[$key])) {\n        throw new InvalidArgumentException(\"Parameter {$key} violates pattern {$pattern}\");\n    }\n}","typeGuard":"function canGenerateUrl(string $name, array $url): bool {\n    $route = Router::getRouteCollection()->get($name);\n    return $route !== null && (bool)$route->match($url, []);\n}","tryCatchPattern":"try {\n    $url = Router::url(['_name' => 'articles:view', 'id' => $id]);\n} catch (Cake\\Routing\\Exception\\MissingRouteException $e) {\n    Log::error('Named route match failed: ' . $e->getMessage());\n    $url = '/';\n}","preventionTips":["Keep named-route parameter keys in sync with route templates; prefer named routes with explicit placeholders","Add integration tests that generate a URL for every named route in routes.php (like testPluginRoutes does)","Review route pattern constraints (\\d+ etc.) when identifiers can be non-numeric","Grep for Router::url(['_name' => ...]) whenever a route template changes"],"tags":["routing","cakephp","url-generation","missing-route"],"backgroundTag":"resource-not-found","analyzedSha":"1128eba9b09f1946df684811350e26f2cef68fac","analyzedAt":"2026-09-12T12:07:00.388Z","contentChangedAt":"2026-09-12T12:07:00.388Z","schemaVersion":2},"datasetVersion":"2026-09-19T12:17:13.211Z"}