Laravel error
Laravel: Route [login] not defined
The error
Route [login] not defined.An unauthenticated request reached a guarded route, and the framework tried to redirect to a named route your application does not have. The error is about the redirect, not about authentication.
The error
Symfony\Component\Routing\Exception\RouteNotFoundException
Route [login] not defined.
Thrown from inside the authentication middleware, usually with a stack trace
that mentions Authenticate::redirectTo or UrlGenerator::route.
What it means
This is not a failure to authenticate. Authentication already failed - that part worked correctly. What broke is what happened next.
When the auth middleware rejects a request it has to decide what to send
back, and for a browser the answer is a redirect to the login page. It finds
that page by asking the router for a route named login. Your application
does not have one, so the router throws.
So the real question is not "why is authentication failing" but "why is this request being treated as a browser request".
If you are building an API
The usual case, and the usual cause is a missing header.
The middleware decides between a redirect and a 401 by asking whether the
request expects JSON, which it reads from Accept. A client sending
Accept: application/json gets a clean 401. A client sending nothing, or
*/*, looks like a browser and gets sent looking for a login page.
Fix it on the client where you can - it is one header and it is correct anyway:
Accept: application/json
And fix it on the server so it cannot happen again, because you do not control every client:
// bootstrap/app.php
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo(fn () => null);
})Returning null means there is no redirect target, so the framework raises an
AuthenticationException and the handler turns it into a 401 with a JSON
body. That is the right response for an API regardless of what the caller
sent.
Where an application serves both a web interface and an API, make it conditional rather than global:
$middleware->redirectGuestsTo(
fn (Request $request) => $request->is('api/*') ? null : route('web.login')
);If you do have a login page
Then the route exists and the name does not. Check:
php artisan route:list --name=loginEmpty output, and one of these applies.
The route has no name. A route defined as
Route::get('/login', [LoginController::class, 'show']) is reachable and
anonymous. Add ->name('login').
The name is different. auth.login, user.login, signin. The framework
looks for exactly login, so either rename the route or tell the middleware
what your name is, using the callback above.
The route is behind a prefix or a group that is not loaded. A login route inside a route file that is only registered for one domain, or a group whose condition is false in this environment, will not be in the list.
The route cache is stale. Built before the route existed:
php artisan route:clearThe variant worth recognising
The same error with [password.request], [verification.notice] or
[register] in the brackets is the same problem in a different feature.
Password reset, email verification and registration each assume a named route
that a starter kit would have created and a hand-rolled auth system did not.
The fix is the same: provide the name, or tell the framework what your name is.
The commonest way to meet this is not a missing route at all. It is a session that expired and a 419 that redirects towards a login page whose route was never named.
On an API it is usually the wrong middleware: a JSON client sent towards a login page it cannot render. The token package you are on decides what should happen instead, and getting that boundary right is most of what API work is.
