The Power of SANCTUM_STATEFUL_DOMAINS
If your Laravel + Sanctum + Inertia or SPA setup works perfectly in local development but suddenly fails in production with mysterious 401 Unauthorized
errors — you’re not alone guys. One of the most common causes is misconfigured SANCTUM_STATEFUL_DOMAINS
, which controls which domains should be treated as stateful (session-based) instead of stateless (token-based). This article explains why the error Laravel Sanctum 401 Unauthorized on Production happens, how to fix it quickly using Laravel’s built-in tools, and how to write your sanctum.php
config to avoid future problems.
What Is the 401 Unauthorized Error in Laravel Sanctum?
401 Error in Production, But Not Locally?
If you’re seeing this error:
GET https://yourdomain.com/api/dashboard 401 (Unauthorized)
It means that Laravel doesn’t recognize the current user as authenticated. This happens because the session cookie wasn’t attached to the request, or Laravel ignored it due to domain mismatch.
Why This Happens: Sanctum Treats the Domain as Stateless?
By default, Laravel Sanctum will only treat requests from certain domains as stateful — and reject others with 401, even if the user is already logged in.
This is controlled via:
SANCTUM_STATEFUL_DOMAINS=localhost,127.0.0.1
If your production domain is not listed here, Sanctum won’t read cookies or session data, and will treat the request as unauthenticated, resulting in a 401 Unauthorized
.
Solution: Update your SANCTUM_STATEFUL_DOMAINS
in config/sanctum.php
Instead of hardcoding domains, you can dynamically detect the current host and append it:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
'%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,yourdomain.com,',
Sanctum::currentApplicationUrlWithPort()
))),
This line appends the current app’s URL (with port) to the default list of trusted stateful domains. This means even if your server changes or you’re testing from multiple domains, your authentication still works.