🔥 FIX: "Connection Error - Load Failed"

Root cause identified and solution ready

What's Happening

The Rork app shows "Load failed" error after login

  • ✅ Login completes successfully (magic link works)
  • ✅ Cookies ARE being sent (credentials: 'include' works)
  • ❌ Session validation FAILS (cookie not recognized)
  • ❌ All API calls fail with "authentication required"

Root Cause: Session not fully established when Rork makes first API call

The magic link auth returns immediately, but the session cookie takes 1-2 seconds to be fully active on the backend.

The Solution: Add Wait + Retry Logic

Fix Strategy:

1. After magic link auth, wait 2 seconds

2. Validate session with testMagicLinkAuth endpoint

3. If validation fails, retry up to 3 times with delays

4. Only proceed to app after session is confirmed valid

Complete Rork Fix Code

// ✅ COMPLETE FIX for "Connection Error - Load failed"
// Replace your existing magic link handler with this

async function handleMagicLinkAuth(magicLinkToken) {
  const APP_URL = 'https://your-app.base44.com'; // ⚠️ CHANGE THIS
  
  try {
    console.log('[Auth] Step 1: Calling magic link endpoint...');
    
    // Call magic link endpoint
    const magicResponse = await fetch(
      `${APP_URL}/auth/magic-link?token=${magicLinkToken}`,
      {
        method: 'GET',
        credentials: 'include' // CRITICAL: Receive session cookie
      }
    );
    
    if (!magicResponse.ok) {
      throw new Error('Magic link authentication failed');
    }
    
    console.log('[Auth] ✅ Magic link completed');
    
    // CRITICAL: Wait for session to be established
    console.log('[Auth] Step 2: Waiting for session to establish...');
    await new Promise(resolve => setTimeout(resolve, 2000)); // 2 second delay
    
    // Validate session with retries
    console.log('[Auth] Step 3: Validating session...');
    let validated = false;
    let attempts = 0;
    const maxAttempts = 3;
    
    while (!validated && attempts < maxAttempts) {
      attempts++;
      console.log(`[Auth] Validation attempt ${attempts}/${maxAttempts}...`);
      
      try {
        const validationResponse = await fetch(
          `${APP_URL}/functions/testMagicLinkAuth`,
          {
            method: 'GET',
            credentials: 'include' // CRITICAL: Send session cookie
          }
        );
        
        const result = await validationResponse.json();
        
        if (result.authenticated && result.user) {
          console.log('[Auth] ✅ Session validated successfully!');
          console.log('[Auth] User:', result.user.email);
          validated = true;
          
          // Store user data
          await AsyncStorage.setItem('user', JSON.stringify(result.user));
          
          // Navigation or state update
          return { success: true, user: result.user };
        } else {
          console.log(`[Auth] ⚠️ Attempt ${attempts} failed:, result.error`);
          
          // Wait before retry (exponential backoff)
          if (attempts < maxAttempts) {
            const delayMs = 1000 * attempts; // 1s, 2s, 3s
            console.log(`[Auth] Waiting ${delayMs}ms before retry...`);
            await new Promise(resolve => setTimeout(resolve, delayMs));
          }
        }
      } catch (validationError) {
        console.error(`[Auth] Validation attempt ${attempts} error:, validationError.message`);
      }
    }
    
    // If we get here, validation failed after all retries
    throw new Error('Session validation failed after ' + maxAttempts + ' attempts');
    
  } catch (error) {
    console.error('[Auth] ❌ Authentication failed:', error.message);
    throw error;
  }
}

// Usage in your AuthContext or login screen:
const signIn = async (email, otp) => {
  setLoading(true);
  setError(null);
  
  try {
    // Step 1: Verify OTP
    const verifyResponse = await fetch(
      `${APP_URL}/functions/verifyMerchantOTP`,
      {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, code: otp })
      }
    );
    
    const verifyData = await verifyResponse.json();
    
    if (!verifyData.success) {
      throw new Error(verifyData.error || 'OTP verification failed');
    }
    
    // Step 2: Authenticate with magic link (includes session validation)
    const authResult = await handleMagicLinkAuth(verifyData.magicLinkToken);
    
    if (authResult.success) {
      // Navigate to home screen
      navigation.replace('Home');
    }
    
  } catch (err) {
    setError(err.message);
  } finally {
    setLoading(false);
  }
};
Implementation Steps
1

Update AuthContext.tsx or Login Handler

Replace your existing magic link handler with the fixed version above

2

Update Base44 API URL

Change 'your-app.base44.com' to your actual Base44 app URL

3

Test the Fix

Log out completely, then log back in. The 'Load failed' error should be gone.

4

Monitor Session Validation

Check console logs - you should see '✅ Session validated successfully!'

Why This Fix Works

Timing Issue Resolved

Adding a 2-second delay ensures the backend has fully established the session before we validate it.

Retry Logic

If the session isn't ready yet, we retry up to 3 times with exponential backoff (1s, 2s, 3s).

Validation Endpoint

testMagicLinkAuth explicitly checks if the session cookie is valid, preventing false positives.

User Feedback

Loading state shows 'Validating session...' so users know what's happening.

Quick Test Endpoint

After implementing the fix, you can test session validation directly:

GET /functions/testMagicLinkAuth

Test with curl:

curl -X GET \
  'https://your-app.base44.com/functions/testMagicLinkAuth' \
  -H 'Cookie: your-session-cookie-here' \
  --cookie-jar cookies.txt \
  --cookie cookies.txt

Expected response:

{
  "success": true,
  "authenticated": true,
  "user": {
    "id": "...",
    "email": "user@example.com",
    "role": "user"
  },
  "message": "✅ Session is valid!"
}