Authentication Error Codes
Reference for all authentication-related error responses.
HTTP Status Codes
| Status |
Title |
Description |
| 200 |
OK |
Request succeeded |
| 201 |
Created |
Resource created successfully |
| 401 |
Unauthorized |
Authentication required or failed |
| 403 |
Forbidden |
Insufficient permissions |
| 404 |
Not Found |
Resource not found |
| 422 |
Unprocessable Entity |
Validation failed |
| 423 |
Locked |
Resource locked (concurrent login pending) |
| 429 |
Too Many Requests |
Rate limit exceeded |
| 500 |
Internal Server Error |
Server error |
All errors follow this format:
{
"detail": "Error message"
}
For some errors, additional context is provided:
{
"detail": {
"status": "pending",
"token": "concurrent-login-token"
}
}
Authentication Errors (401)
| Error Code |
Message |
Cause |
Solution |
not_authenticated |
Not authenticated |
No valid access token provided |
User must login |
token_expired |
Token has expired |
Access token TTL exceeded |
Client must refresh token |
token_invalid_signature |
Invalid token signature |
Token tampered or wrong secret |
Check JWT_SECRET_KEY |
token_validation_failed |
Invalid token |
Malformed or invalid token |
User must re-login |
preauth_expired |
Pre-auth token expired |
Pre-auth token TTL exceeded |
User must restart login flow |
credentials_invalid |
Invalid credentials |
Email or password incorrect |
User should retry or reset password |
email_verification_required |
Email verification required |
User email not verified |
User must verify email first |
Authorization Errors (403)
| Error Code |
Message |
Cause |
Solution |
missing_permission |
Missing permission: {perm} |
User lacks required permission |
Grant permission to user's role |
csrf_mismatch |
CSRF token mismatch |
CSRF cookie/header mismatch |
Ensure CSRF token sent correctly |
team_status_not_allowed |
Team is not active or trialing |
Team status not in |
Contact support |
concurrent_login_denied |
Concurrent login denied |
Existing user denied new login |
Existing session must approve first |
vz_refresh_forbidden |
Only Owner can refresh Virtuozzo session |
Non-owner attempted VZ refresh |
Owner must perform action |
Concurrent Login Errors (423)
| Error Code |
Message |
Cause |
Solution |
concurrent_login_pending |
Concurrent login approval pending |
Another active session exists |
User must approve/deny via existing session or email |
Response Format:
{
"detail": {
"status": "pending",
"token": "concurrent-login-token"
}
}
Validation Errors (422)
| Field |
Error |
Cause |
Solution |
email |
Invalid email format |
Email doesn't match regex |
Provide valid email |
password |
Password too short |
Password < 8 characters |
Use longer password |
password |
Password too weak |
Missing complexity |
Include letters, numbers, symbols |
team_slug |
Invalid slug format |
Contains invalid characters |
Use lowercase, letters, numbers, hyphens |
otp_code |
Invalid OTP format |
Not 6 digits |
Provide 6-digit code |
token |
Invalid token format |
Token malformed or wrong length |
Check token from email |
Rate Limiting Errors (429)
| Error Code |
Message |
Cause |
Solution |
rate_limit_exceeded |
Too many attempts. Try again later. |
Login rate limit exceeded |
Wait for window to expire |
Headers:
Virtuozzo Integration Errors
| Error Code |
Message |
Cause |
Solution |
vz_connection_error |
Virtuozzo API unavailable |
Network or API issue |
Check VZ service status |
vz_auth_error |
Virtuozzo authentication failed |
Invalid VZ credentials |
Owner must re-authenticate |
vz_timeout |
Virtuozzo API timeout |
Request took too long |
Retry or increase timeout |
vz_session_refresh_failed |
Failed to refresh Virtuozzo session |
VZ API returned error |
Owner must update VZ credentials |
Email Errors
| Error Code |
Message |
Cause |
Solution |
email_send_failed |
Failed to send email |
Postmark API error |
Check Postmark credentials |
email_template_missing |
Email template not configured |
Template ID not set |
Configure template in env |
email_rate_limit_exceeded |
Email rate limit exceeded |
Too many emails sent |
Wait for rate limit to reset |
Database Errors
| Error Code |
Message |
Cause |
Solution |
user_not_found |
User not found |
Invalid user_id |
Check user exists |
team_not_found |
Team not found |
Invalid team_id |
Check team exists |
membership_not_found |
Team membership not found |
User not in team |
Check membership |
invite_not_found |
Invite token not found |
Invalid or expired token |
Generate new invite |
invite_already_used |
Invite already used |
Token already consumed |
Use fresh invite |
Session Errors
| Error Code |
Message |
Cause |
Solution |
session_not_found |
Session not found |
Invalid refresh JTI |
User must re-login |
session_expired |
Session expired |
Idle timeout exceeded |
User must re-login |
session_revoked |
Session revoked |
Session was revoked |
User must re-login |
session_inactive |
Session inactive |
Idle timeout exceeded |
User must re-login |
Device Approval Errors
| Error Code |
Message |
Cause |
Solution |
otp_invalid |
Invalid OTP code |
Wrong or expired OTP |
User should retry |
otp_attempts_exceeded |
Too many OTP attempts |
Max attempts exceeded |
Request new OTP |
device_already_trusted |
Device already trusted |
Device already approved |
Proceed with login |
device_not_found |
Device not found |
Invalid device_id |
Check device ID |
Troubleshooting
User sees "Not authenticated"
- Check if access token cookie is present
- Verify token hasn't expired
- Check
JWT_SECRET_KEY matches between services
- Verify middleware is correctly configured
User sees "Missing permission"
- Check user's role via
/api/v1/auth/me
- Verify role has required permission
- Check permission slug matches exactly
- Ensure wildcard
* permission for Owners
User sees "CSRF token mismatch"
- Ensure CSRF cookie is being sent
- Verify CSRF header is set:
X-CSRF-Token
- Check cookie domain/path settings
- Ensure SameSite attribute is compatible
User sees "Concurrent login pending"
- User has existing active session
- Existing session must approve new login
- Or user can deny and force logout from existing session
- Check
ActiveSession table for current state
Rate limiting triggered
- Check
LOGIN_RATE_LIMIT_* settings
- Monitor Redis for rate limit keys:
rl:login:*
- Adjust window or max attempts if needed
- Check for abusive IP patterns