How to debug 404 on user/login user/register user/logout? I have a Drupal 8 site on 8.4.2.  When I upgrade it to 8.5.1, after running the database updates, the paths /user/register, /user/login, and /user/logout return a 404.


I can log in with Drush (drush uli myuser), so it is possible to actually log in, but the log in page is not displayed.
I tried uninstalling my custom modules, but the problem persists.
I looked at /admin/reports/dblog, but it just says "page not found" as the error for /user/login.


This question about a similar problem was closed as off topic because it was too specific; my question is about "how can I debug this?" not "what is the cause of my problem?"
@AndrewKillen:


  Checked with Devel and it says "Unable to load route for url
  '/user/login'" when checking the user.login route.


How this could be debugged (on an working example, because I don't have a broken site):

Enable Xdebug and go to the url: /devel/routes/item?path=/user/login

Drupal\devel\Controller\RouteInfoController::routeDetail:

  public function routeDetail(Request $request, RouteMatchInterface $route_match) {
    $route = NULL;

    // Get the route object from the path query string if available.
    if ($path = $request-&gt;query-&gt;get('path')) {
      try {
        $route = $this-&gt;router-&gt;match($path);


Set a breakpoint for the last line and step into match($path). Then after a new request with the path info is created you get to:

Router::matchRequest:

  public function matchRequest(Request $request) {
    $collection = $this-&gt;getInitialRouteCollection($request);
    if ($collection-&gt;count() === 0) {
      throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $this-&gt;currentPath-&gt;getPath()));
    }
    $collection = $this-&gt;applyRouteFilters($collection, $request);

    if ($ret = $this-&gt;matchCollection(rawurldecode($this-&gt;currentPath-&gt;getPath($request)), $collection)) {
      return $this-&gt;applyRouteEnhancers($ret, $request);
    }


getInitialRouteCollection() results in three possible matches:


user.login
user.login.http
entity.user.canonical


The second one is filtered in applyRouteFilters() because this is POST only and for JSON. The entity route is removed after the compiled routes are matched in matchCollection() because "login" is not a valid user.

And so the route user.login is the last one remaining and returned. If not you have to check where on this way the route is not collected or filtered out.