Session Error Troubleshooting

Specific troubleshooting for SCORM session creation and management errors.

Table of Contents

Creation Errors

Error: "Package not found"

Cause: Package ID doesn't exist or belongs to different tenant.

Solutions:

  1. Verify Package ID:

    curl -X GET "https://app.allureconnect.com/api/v1/packages/pkg_abc123" \
      -H "X-API-Key: your-api-key"
    
  2. Check Tenant:

    • Ensure package belongs to your tenant
    • Verify API key tenant matches
    • Check package hasn't been deleted
  3. Verify Format:

    • Package ID must be UUID format
    • Check for typos
    • Verify ID is complete

Error: "Invalid user_id"

Cause: User ID format is invalid.

Solutions:

  1. Check Format:

    • User ID can be any string (up to 255 chars)
    • Must be non-empty
    • Avoid special characters that break URLs
  2. Recommended Format:

    // Use UUID or your system's user identifier
    const userId = user.id; // e.g., "user_123" or UUID
    
  3. URL Encoding:

    • Encode user ID if contains special chars
    • Use encodeURIComponent() for URLs
    • Avoid spaces and special characters

Error: "Session already exists"

Cause: Session with same ID already exists.

Solutions:

  1. Use Unique Session IDs:

    // Generate unique session ID
    const sessionId = crypto.randomUUID();
    
  2. Check Existing Sessions:

    curl -X GET "https://app.allureconnect.com/api/v1/sessions?user_id=user_123&package_id=pkg_abc123" \
      -H "X-API-Key: your-api-key"
    
  3. Resume Existing Session:

    • Check for incomplete sessions
    • Resume instead of creating new
    • Reuse existing session ID

Update Errors

Error: "Version conflict" (409)

Cause: Session was updated by another process.

Solutions:

  1. Implement Retry Logic:

    async function updateSessionWithRetry(
      sessionId: string,
      updates: any,
      maxRetries = 3
    ) {
      for (let attempt = 0; attempt < maxRetries; attempt++) {
        // Get current session
        const session = await fetch(
          `/api/v1/sessions/${sessionId}`,
          { headers: { 'X-API-Key': apiKey } }
        ).then(r => r.json());
    
        // Merge updates
        const payload = {
          version: session.version, // Use current version
          ...updates
        };
    
        // Attempt update
        const response = await fetch(
          `/api/v1/sessions/${sessionId}`,
          {
            method: 'PUT',
            headers: {
              'X-API-Key': apiKey,
              'Content-Type': 'application/json'
            },
            body: JSON.stringify(payload)
          }
        );
    
        if (response.ok) {
          return await response.json();
        }
    
        if (response.status === 409 && attempt < maxRetries - 1) {
          await delay(100 * (attempt + 1));
          continue;
        }
    
        throw new Error(`Update failed: ${response.status}`);
      }
    }
    
  2. Always Include Version:

    • Never update without version
    • Always fetch latest before update
    • Use optimistic locking correctly
  3. Handle Concurrent Updates:

    • Merge changes intelligently
    • Don't overwrite other updates
    • Preserve important data

Error: "Session not found"

Cause: Session doesn't exist or was deleted.

Solutions:

  1. Verify Session ID:

    • Check session ID is correct
    • Verify session exists
    • Check session hasn't expired
  2. Check Session Status:

    curl -X GET "https://app.allureconnect.com/api/v1/sessions/session_123" \
      -H "X-API-Key: your-api-key"
    
  3. Handle Expiration:

    • Sessions expire after inactivity
    • Create new session if expired
    • Check expiration time

Launch Errors

Error: "Session expired"

Cause: Session has expired.

Solutions:

  1. Check Expiration:

    const session = await getSession(sessionId);
    const expiresAt = new Date(session.expires_at);
    
    if (expiresAt < new Date()) {
      // Session expired, create new one
      const newSession = await launchSession(packageId, userId);
    }
    
  2. Refresh Session:

    • Create new session
    • Update launch URL
    • Notify user of expiration
  3. Extend Expiration:

    • Some plans allow longer sessions
    • Contact support for custom expiration
    • Consider session renewal

Error: "Invalid launch token"

Cause: Launch token is invalid or expired.

Solutions:

  1. Regenerate Launch:

    const launch = await fetch(
      `/api/v1/packages/${packageId}/launch`,
      {
        method: 'POST',
        headers: {
          'X-API-Key': apiKey,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          user_id: userId,
          session_id: sessionId
        })
      }
    ).then(r => r.json());
    
  2. Check Token Expiration:

    • Tokens expire after set time
    • Default: 10 minutes
    • Regenerate if expired
  3. Verify Token Format:

    • Token must be valid JWT
    • Check token hasn't been modified
    • Verify token signature

Progress Tracking Errors

Error: "CMI data update failed"

Cause: Failed to update CMI data.

Solutions:

  1. Check CMI Data Format:

    const cmiData = {
      "cmi.core.lesson_status": "completed",
      "cmi.core.score.raw": "85",
      "cmi.core.score.max": "100"
    };
    
  2. Validate Data Types:

    • Strings for text fields
    • Numbers for score fields
    • Valid SCORM data model values
  3. Handle Version Conflicts:

    • Implement retry logic
    • Merge updates correctly
    • Use optimistic locking

Error: "Progress not updating"

Cause: Progress updates not being saved.

Solutions:

  1. Check Update Frequency:

    • Don't update too frequently
    • Batch updates when possible
    • Use appropriate intervals
  2. Verify Update Success:

    const response = await updateSession(sessionId, updates);
    if (!response.ok) {
      console.error('Update failed:', await response.text());
    }
    
  3. Check Session Status:

    • Verify session is active
    • Check session hasn't expired
    • Ensure session is accessible

Best Practices

1. Always Handle Version Conflicts

async function safeUpdateSession(sessionId: string, updates: any) {
  try {
    return await updateSessionWithRetry(sessionId, updates);
  } catch (error) {
    if (error.message.includes('409')) {
      // Version conflict - retry
      return await safeUpdateSession(sessionId, updates);
    }
    throw error;
  }
}

2. Check Session Before Operations

async function ensureSession(sessionId: string) {
  const session = await getSession(sessionId);
  
  if (!session) {
    throw new Error('Session not found');
  }
  
  if (new Date(session.expires_at) < new Date()) {
    throw new Error('Session expired');
  }
  
  return session;
}

3. Implement Proper Error Handling

async function launchCourse(packageId: string, userId: string) {
  try {
    const launch = await launchSession(packageId, userId);
    return launch;
  } catch (error) {
    if (error.status === 404) {
      // Package not found
      throw new Error('Course not available');
    } else if (error.status === 403) {
      // Access denied
      throw new Error('Access denied');
    } else {
      // Other error
      console.error('Launch failed:', error);
      throw new Error('Failed to launch course');
    }
  }
}

Related Documentation


Last Updated: 2025-01-15