{"id":"c26565ab26390f5c","repo":"laravel/framework","slug":"your-email-address-is-not-verified","errorCode":null,"errorMessage":"Your email address is not verified.","messagePattern":"Your email address is not verified\\.","errorType":"http","errorClass":"HttpException","httpStatus":403,"severity":"error","filePath":"src/Illuminate/Auth/Middleware/EnsureEmailIsVerified.php","lineNumber":37,"sourceCode":"    {\n        return static::class.':'.$route;\n    }\n\n    /**\n     * Handle an incoming request.\n     *\n     * @param  \\Illuminate\\Http\\Request  $request\n     * @param  \\Closure  $next\n     * @param  string|null  $redirectToRoute\n     * @return \\Illuminate\\Http\\Response|\\Illuminate\\Http\\RedirectResponse|null\n     */\n    public function handle($request, Closure $next, $redirectToRoute = null)\n    {\n        if (! $request->user() ||\n            ($request->user() instanceof MustVerifyEmail &&\n            ! $request->user()->hasVerifiedEmail())) {\n            return $request->expectsJson()\n                ? abort(403, 'Your email address is not verified.')\n                : Redirect::guest(URL::route($redirectToRoute ?: 'verification.notice'));\n        }\n\n        return $next($request);\n    }\n}\n","sourceCodeStart":19,"sourceCodeEnd":44,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Auth/Middleware/EnsureEmailIsVerified.php#L19-L44","documentation":"Produced by EnsureEmailIsVerified middleware via abort(403, 'Your email address is not verified.') — only when the request expects JSON. For non-JSON requests it redirects to the verification.notice route (or a custom $redirectToRoute). The 403 fires when there is no authenticated user OR the user implements MustVerifyEmail and has not verified their email. This is an HTTP-level access-control response, not a thrown exception a caller catches in normal PHP flow.","triggerScenarios":"Applying the 'verified' middleware aliasus (EnsureEmailIsVerified) to a route and hitting it via an API client that sets Accept: application/json while the user is unverified (or not logged in). Common with SPA/mobile clients that always send Accept JSON.","commonSituations":"Forgetting to send the email verification after registration. Users who registered but never clicked the verification link. Token/session expired so $request->user() is null. SPA defaults to JSON and never sees the redirect, getting a raw 403 instead.","solutions":["Trigger email verification: send the verification link via the verification.send route (Event dispatch EmailVerificationRequested).","Mark the user verified manually in tests/dev: $user->markEmailAsVerified();.","Ensure the route is also behind the 'auth' middleware so $request->user() is non-null.","For APIs, return a structured JSON error/redirect URL instead of bare abort by customizing the middleware or adding an after-handler.","Exclude the route from the verified middleware if it must be publicly accessible."],"exampleFix":"// before — routes/web.php\nRoute::get('/api/profile', fn () => ...)->middleware(['auth', 'verified']);\n\n// after — trigger verification + ensure user is set\nuse Illuminate\\Auth\\Middleware\\EnsureEmailIsVerified;\n\nRoute::get('/email/verify', fn () => view('auth.verify'))->name('verification.notice');\nRoute::post('/email/verification-notification', function (\\Illuminate\\Http\\Request $request) {\n    $request->user()->sendEmailVerificationNotification();\n    return back()->with('status', 'verification-link-sent');\n})->middleware(['auth', 'throttle:6,1'])->name('verification.send');\n\n// In tests, verify the user first:\n$user = User::factory()->create(['email_verified_at' => now()]);\n$this->actingAs($user);","handlingStrategy":"validation","validationCode":"// In a controller/middleware, verify before relying on 'verified':\n$user = $request->user();\nif (! $user || ($user instanceof \\Illuminate\\Contracts\\Auth\\MustVerifyEmail && ! $user->hasVerifiedEmail())) {\n    return response()->json(['message' => 'Email verification required.', 'verify_url' => route('verification.notice')], 403);\n}","typeGuard":"use Illuminate\\Contracts\\Auth\\MustVerifyEmail;\n\nfunction emailVerifiedForRequest(\\Illuminate\\Http\\Request $request): bool {\n    $user = $request->user();\n    return $user !== null\n        && (! $user instanceof MustVerifyEmail || $user->hasVerifiedEmail());\n}","tryCatchPattern":"// abort(403) is an HttpResponseException; you cannot catch it as a normal exception in the\n// controller that hits the middleware. Catch globally in an API exception handler for structured JSON:\n// app/Exceptions/Handler.php\npublic function register(): void {\n    $this->renderable(function (\\Symfony\\Component\\HttpKernel\\Exception\\HttpException $e, $request) {\n        if ($e->getStatusCode() === 403 && $e->getMessage() === 'Your email address is not verified.' && $request->expectsJson()) {\n            return response()->json([\n                'message' => 'Email not verified.',\n                'action'  => 'verify_email',\n                'resend_url' => route('verification.send'),\n            ], 403);\n        }\n    });\n}","preventionTips":["Always send the verification email on registration (dispatch EmailVerificationRequested / ShouldQueue notification).","In tests, mark users verified: $user->markEmailAsVerified() or User::factory()->create(['email_verified_at' => now()]).","Pair 'verified' with 'auth' so $request->user() is non-null.","For APIs, override the 403 render to return a structured JSON error with the resend link."],"tags":["auth","middleware","email-verification","http-403","access-control"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}