Skip to content
Reference

Troubleshooting

Organised by what you are seeing, not by what causes it, because the error is the part you have. Find your symptom, apply the fix, carry on.

401 on a route that should work#

A 401 always means the same thing: FastAuth could not establish who you are. Work down this list in order.

401 · Not authenticated

No token arrived at all. Confirm the request carries either an Authorization: Bearer <token> header or the auth cookie. In /docs, this means clicking Authorize and logging in first.

401 · FASTAUTH_INVALID_TOKEN

A token arrived but did not verify. In order of likelihood: it expired (30 minutes by default, so log in again); your secret_key changed since the token was issued, which invalidates every existing token; or you sent a refresh token where an access token was expected.

401 · FASTAUTH_INVALID_CREDENTIALS on /token

The username or password is wrong. If you changed the code that seeds your admin, the user in the database still has the old password — delete the SQLite file and restart, or reset the password deliberately.

Everyone was logged out at once, with no deploy

Your secret_key is not stable between restarts. If you never set one, FastAuth generates a development secret and stores it in .fastauth-secret; if that file is not persisted, every restart mints a new key and invalidates every token. Set SECRET_KEY in the environment.

403 when the user is definitely logged in#

A 403 means the opposite of a 401: you are authenticated fine, and the answer is still no. Sending the user to the login page will not help.

403 · FASTAUTH_PERMISSION_DENIED

The account is missing a role the route requires. Check what it actually holds with GET /roles/user/{user_id}, and assign one with POST /roles/assign/{user_id}/{role_id}. Remember auth.all_roles(...) requires every listed role, not any of them.

403 · FASTAUTH_INACTIVE_USER

The user's disabled column is True. This is checked at login, at refresh, and on every protected route.

403 · FASTAUTH_EMAIL_NOT_VERIFIED

The route depends on auth.verified_user and this account has not confirmed its address. Send them through POST /email/verify/request, or use auth.current_user if verification is not actually required here.

Cookies are not being set or sent#

Login succeeds but the browser has no cookie

Either use_cookie=False (it is off by default), or cookie_secure=True while you are browsing over plain http://. A Secure cookie is silently discarded by the browser on a non-HTTPS origin — no error, it simply never appears. Use cookie_secure=False in development.

The cookie exists but protected routes still 401

The browser is not sending it cross-origin. If your frontend is on a different port or domain from the API, the request needs credentials: "include", your CORS middleware needs allow_credentials=True, and allow_origins cannot be ["*"] when credentials are enabled.

Auth works locally but breaks behind a proxy in production

Your app is not seeing HTTPS. Behind a reverse proxy the app receives plain HTTP and considers the connection insecure, so Secure cookies are dropped. Forward X-Forwarded-Proto and run the server with --proxy-headers.

Database and startup#

sqlite3.OperationalError: no such column: user.email_verified

Your database predates v0.6.0, which added email_verified and token_version. Add the columns with ALTER TABLE or an Alembic migration. A development SQLite file can simply be deleted and rebuilt — create_all never alters an existing table, so this will not fix itself.

Startup hangs with no output

initialize_db is waiting on a console prompt for admin credentials that will never come, because there is no terminal attached. Always pass admin_username and admin_password explicitly when initializing at startup.

Table 'user' is already defined for this MetaData instance

Two SQLModel table models are claiming the same table. When using a custom user model, do not also import FastAuth's built-in User anywhere in the app.

Still stuck?#

Turn on your app's logs and look at the actual error.code in the response body rather than the status alone — the codes are listed on error handling and each maps to exactly one cause. If that does not resolve it, open an issue on GitHub with the code, the FastAuth version, and the smallest snippet that reproduces it.