Skip to content

Commit d0d72e8

Browse files
committed
fix: Improve login error handling and database resilience
Better Error Differentiation: - 401 INVALID_CREDENTIALS: Wrong email/password (user error) - 503 SERVICE_UNAVAILABLE: Database/server issues (system error) - Clear error messages for different failure types Database Wake-up for Login: - Retry login with database wake-up on 503/network errors - 2-second wait for database to wake up before retry - Graceful fallback to original error if retry fails Frontend Error Handling: - Specific error messages for different failure types - Network error detection and user-friendly messages - Better UX with actionable error descriptions Now users will know if it's their credentials or if the server is sleeping! 401 = Wrong password, 503 = Database sleeping, Network Error = Connection issue
1 parent 0cd22b0 commit d0d72e8

File tree

3 files changed

+67
-11
lines changed

3 files changed

+67
-11
lines changed

backend/src/controllers/authController.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,30 @@ export class AuthController {
113113
data: result,
114114
});
115115
} catch (error: any) {
116-
res.status(401).json({
117-
error: {
118-
code: 'LOGIN_FAILED',
119-
message: error.message,
120-
},
121-
timestamp: new Date().toISOString(),
122-
path: req.path,
123-
});
116+
// Check if it's a database/server error vs authentication error
117+
if (error.message === 'Invalid email or password') {
118+
// Legitimate authentication failure
119+
res.status(401).json({
120+
error: {
121+
code: 'INVALID_CREDENTIALS',
122+
message: error.message,
123+
},
124+
timestamp: new Date().toISOString(),
125+
path: req.path,
126+
});
127+
} else {
128+
// Likely a server/database error
129+
console.error('Login server error:', error);
130+
res.status(503).json({
131+
error: {
132+
code: 'SERVICE_UNAVAILABLE',
133+
message: 'Login service temporarily unavailable. Please try again in a moment.',
134+
details: process.env.NODE_ENV === 'development' ? error.message : undefined,
135+
},
136+
timestamp: new Date().toISOString(),
137+
path: req.path,
138+
});
139+
}
124140
}
125141
}
126142

frontend/src/contexts/AuthContext.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,22 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children
5757
// Set user
5858
setUser(response.user)
5959
} catch (error: any) {
60-
const message = error.response?.data?.error?.message || 'Login failed'
60+
let message = 'Login failed'
61+
62+
if (error.response?.data?.error) {
63+
const errorData = error.response.data.error
64+
65+
if (errorData.code === 'INVALID_CREDENTIALS') {
66+
message = 'Invalid email or password. Please check your credentials and try again.'
67+
} else if (errorData.code === 'SERVICE_UNAVAILABLE') {
68+
message = 'Login service is temporarily unavailable. Please try again in a moment.'
69+
} else {
70+
message = errorData.message || 'Login failed'
71+
}
72+
} else if (error.code === 'ERR_NETWORK') {
73+
message = 'Unable to connect to the server. Please check your internet connection and try again.'
74+
}
75+
6176
throw new Error(message)
6277
}
6378
}

frontend/src/services/authService.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,33 @@ export interface UsernameAvailabilityResponse {
4646
export const authService = {
4747
// Authentication
4848
async login(data: LoginRequest): Promise<AuthResponse> {
49-
const response = await api.post('/auth/login', data)
50-
return response.data.data
49+
try {
50+
const response = await api.post('/auth/login', data)
51+
return response.data.data
52+
} catch (error: any) {
53+
// If we get a 503 (service unavailable), try to wake up the database and retry once
54+
if (error.response?.status === 503 || error.code === 'ERR_NETWORK') {
55+
console.log('Login failed, attempting to wake up database and retry...')
56+
57+
try {
58+
// Try to wake up the database
59+
await api.get('/wake')
60+
61+
// Wait a moment for the database to wake up
62+
await new Promise(resolve => setTimeout(resolve, 2000))
63+
64+
// Retry the login
65+
const response = await api.post('/auth/login', data)
66+
return response.data.data
67+
} catch (retryError) {
68+
// If retry fails, throw the original error
69+
throw error
70+
}
71+
}
72+
73+
// For other errors (like 401), throw immediately
74+
throw error
75+
}
5176
},
5277

5378
async register(data: RegisterRequest): Promise<AuthResponse> {

0 commit comments

Comments
 (0)