118 lines
3.5 KiB
Markdown
118 lines
3.5 KiB
Markdown
# Session Exists Error - Fix Documentation
|
|
|
|
## Problem
|
|
|
|
When a user was already signed in and attempted to access the sign-in screen, Clerk would throw a `session_exists` error:
|
|
|
|
```json
|
|
{
|
|
"clerkError": true,
|
|
"code": "api_response_error",
|
|
"status": 400,
|
|
"errors": [
|
|
{
|
|
"code": "session_exists",
|
|
"message": "Session already exists",
|
|
"longMessage": "You're already signed in.",
|
|
"meta": {}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
This occurred because:
|
|
1. The sign-in/sign-up screens didn't check if a user was already authenticated before rendering
|
|
2. The error handling didn't gracefully handle the `session_exists` error code
|
|
3. Users could navigate to auth screens even when already signed in
|
|
|
|
## Solution
|
|
|
|
Implemented a two-part fix in both `sign-in.tsx` and `sign-up.tsx`:
|
|
|
|
### 1. Proactive Redirect on Mount
|
|
|
|
Added `useAuth` hook to check authentication status and redirect before any sign-in/sign-up attempts:
|
|
|
|
```typescript
|
|
const { isSignedIn } = useAuth();
|
|
|
|
React.useEffect(() => {
|
|
if (isSignedIn) {
|
|
router.replace('/(tabs)');
|
|
}
|
|
}, [isSignedIn]);
|
|
```
|
|
|
|
### 2. Error Handling for Session Exists
|
|
|
|
Added specific error handling for the `session_exists` error code:
|
|
|
|
```typescript
|
|
catch (err: any) {
|
|
console.error('Sign-in error:', JSON.stringify(err, null, 2));
|
|
|
|
// Handle specific error codes
|
|
if (err.errors?.[0]?.code === 'session_exists') {
|
|
// User is already signed in, just redirect
|
|
router.replace('/(tabs)');
|
|
return;
|
|
}
|
|
|
|
setError(
|
|
err.errors?.[0]?.message ||
|
|
'Failed to sign in. Please check your credentials.'
|
|
);
|
|
}
|
|
```
|
|
|
|
### 3. Loading State UI
|
|
|
|
Added a loading state UI while redirecting to prevent showing the form briefly:
|
|
|
|
```typescript
|
|
if (isSignedIn) {
|
|
return (
|
|
<View style={[styles.container, styles.centerContent]}>
|
|
<ActivityIndicator size="large" color="#2563eb" />
|
|
<Text style={styles.loadingText}>Redirecting...</Text>
|
|
</View>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Files Modified
|
|
|
|
- `apps/mobile/src/app/(auth)/sign-in.tsx` - Added authentication check and session_exists handling
|
|
- `apps/mobile/src/app/(auth)/sign-up.tsx` - Added authentication check and session_exists handling
|
|
|
|
## Testing
|
|
|
|
To test the fix:
|
|
|
|
1. **Sign in normally** - should work as before
|
|
2. **Navigate to sign-in when already signed in** - should immediately redirect to `/(tabs)`
|
|
3. **Try to sign in when already signed in** - should handle gracefully and redirect
|
|
4. **Sign out and sign back in** - should work normally
|
|
|
|
## Root Cause
|
|
|
|
The root cause was that Clerk's authentication state wasn't being checked before allowing users to access or interact with authentication screens. This is a common pattern in auth flows where you want to prevent already-authenticated users from seeing auth screens.
|
|
|
|
## Best Practices Applied
|
|
|
|
1. ✅ **Check auth state on mount** - Prevents unnecessary API calls
|
|
2. ✅ **Handle specific error codes** - Graceful degradation for edge cases
|
|
3. ✅ **Show loading states** - Better UX during redirects
|
|
4. ✅ **Fail safely** - Redirect to app instead of showing errors
|
|
|
|
## Related Documentation
|
|
|
|
- Clerk Expo SDK: https://clerk.com/docs/references/expo/overview
|
|
- Clerk Error Handling: https://clerk.com/docs/custom-flows/error-handling
|
|
- React Navigation Auth Flow: https://reactnavigation.org/docs/auth-flow
|
|
|
|
## Notes
|
|
|
|
- This fix prevents the error from occurring in the first place by checking authentication status
|
|
- The error handling serves as a safety net for edge cases (e.g., race conditions, slow network)
|
|
- The same pattern should be applied to any other authentication-related screens in the future |