Troubleshooting Guide
Common issues, debugging steps, and solutions for class management problems. This guide covers authentication issues, permission errors, content access problems, and ownership transfer difficulties.
Quick Diagnostic Checklist
- ✅ Are you logged in with the correct account?
- ✅ Does your account have educator or admin role?
- ✅ Have you refreshed the page after making changes?
- ✅ Are you the current owner or a content expert for the class?
- ✅ Is your browser allowing cookies (required for Auth v2.0)?
- ✅ Check browser console for JavaScript errors (F12)
Authentication & Access Issues
Problem: 401 Unauthorized Errors
Possible Causes & Solutions
Not Logged In
Solution: Navigate to login page and authenticate with your credentials.
// Check if user is authenticated
const user = await UALS_Auth.getUser();
console.log('Current user:', user);
// If null, redirect to login
if (!user) {
window.location.href = '/login.html';
}
Session Expired
Solution: Log out and log back in to refresh your session.
Cookies Blocked
Solution: UALS Auth v2.0 requires httpOnly cookies. Enable cookies in your browser settings.
Chrome: Settings → Privacy and security → Cookies → Allow all cookies (or exception for uals.app)
Firefox: Settings → Privacy & Security → Standard or Custom (allow cookies)
Missing credentials: 'include' in fetch()
Solution: If you're a developer, ensure all API calls include
credentials: 'include'.
// ✅ CORRECT
fetch('/api/school/classes', {
credentials: 'include',
headers: { 'Content-Type': 'application/json' }
});
// ❌ WRONG - missing credentials
fetch('/api/school/classes', {
headers: { 'Content-Type': 'application/json' }
});
Problem: 403 Forbidden - Access Denied
Common Scenarios
Scenario 1: Content Expert Can't Edit After Ownership Transfer
Root Cause: Content expert invitations are cleared when ownership transfers.
Solution: New owner must re-invite the expert.
// Steps for new owner:
1. Open class details modal
2. Click "Show Content Experts"
3. Click "Add Content Expert"
4. Enter expert's email
5. Submit invitation
Scenario 2: Original Creator Can't Edit After Transfer
Root Cause: Creator role is for audit trail only, not permissions.
Solution: Original creator must be re-invited as content expert by new owner.
Scenario 3: Email Mismatch
Root Cause: User logged in with different email than invitation.
Solution: Verify login email matches invited email exactly (case-sensitive).
// Check current login email
const user = await UALS_Auth.getUser();
console.log('Logged in as:', user.email);
// Compare with class data
const classData = await fetch('/api/school/classes', {
credentials: 'include'
}).then(r => r.json());
const myClass = classData.classes.find(c => c.id === 'class-xxx');
console.log('Owner:', myClass.teacherEmail);
console.log('Experts:', myClass.contentExperts);
Scenario 4: Wrong Role
Root Cause: User account is not educator or admin.
Solution: Contact system administrator to update account role.
// Check user role
const user = await UALS_Auth.getUser();
console.log('User role:', user.role);
// Required roles for class management:
// - 'educator'
// - 'admin'
Content Editing Issues
Problem: Can't Access Content Editor
Debugging Steps
Check User Email
// In browser console:
const user = await UALS_Auth.getUser();
console.log('My email:', user.email);
Check Class Ownership & Experts
// Fetch class data
const classData = await fetch(`/api/school/classes`, {
credentials: 'include'
}).then(r => r.json());
const myClass = classData.classes.find(c => c.id === 'class-xxx');
console.log('Owner:', myClass.teacherEmail);
console.log('Creator:', myClass.creatorEmail);
console.log('Experts:', myClass.contentExperts);
// Your email must be either:
// - myClass.teacherEmail (owner), OR
// - in myClass.contentExperts array
Check Backend Permission Function
If you're a developer debugging server-side issues, check the
canEditClassContent() function in
/src/routes/classContentCache.routes.js.
creatorEmail instead
of teacherEmail. Should be:
const classOwnerEmail = classData.teacherEmail;
if (classOwnerEmail && userEmail === classOwnerEmail) {
return true;
}
Problem: Content Edits Not Saving
Possible Causes & Solutions
-
GCS Connection Issue
- Check
CONTENT_CACHE_METHOD=GCSin environment variables - Verify GCS bucket name and credentials
- Check GCS bucket permissions (writer access required)
- Check
-
Network Timeout
- Large content may timeout - break into smaller chunks
- Check browser Network tab (F12) for failed requests
-
Version Limit Reached
- Maximum 4 versions per hash - oldest is auto-deleted
- This is expected behavior, not an error
Problem: Can't See Other Expert's Edits
Solutions
-
Check Active Version
Expert A may have created a new version without setting it as active. Owner or another expert should set the correct version as active.
-
Refresh Content Cache
Hard refresh the page (Ctrl+Shift+R on Windows, Cmd+Shift+R on Mac)
-
Different Content Hash
If config changed, edits may be on a different hash. Check metadata.json in GCS to see which hash was edited.
Ownership Transfer Issues
Problem: Can't Initiate Transfer
Common Causes
-
Not Current Owner
- Only the current owner (teacherEmail) can initiate transfers
- Original creator (creatorEmail) cannot transfer unless also current owner
-
Pending Transfer Exists
- Only one pending transfer allowed at a time
- Solution: Cancel existing transfer first, then initiate new one
-
Invalid Email Format
- Ensure new owner email is valid format
- Email must match a registered UALS teacher account
Problem: New Owner Doesn't See Pending Transfer
Debugging Steps
Verify Email Match
// New owner checks their login email
const user = await UALS_Auth.getUser();
console.log('Logged in as:', user.email);
// Compare with ownershipTransferPending
const classData = await fetch('/api/school/classes', {
credentials: 'include'
}).then(r => r.json());
classData.classes.forEach(cls => {
if (cls.ownershipTransferPending) {
const pending = JSON.parse(cls.ownershipTransferPending);
console.log('Transfer pending for:', pending.newOwnerEmail);
}
});
Solution: If emails don't match, current owner must cancel and re-initiate with correct email.
Hard Refresh Dashboard
Press Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac) to clear cache and reload.
Check Transfer Was Actually Initiated
Current owner should verify in class details that transfer shows as pending.
Problem: Transfer Accepted But Still Can't Access
Solutions
-
Refresh Dashboard
Hard refresh (Ctrl+Shift+R) or reload the page to update permissions.
-
Check teacherEmail Field
// Verify class ownership updated const classData = await fetch('/api/school/classes', { credentials: 'include' }).then(r => r.json()); const myClass = classData.classes.find(c => c.id === 'class-xxx'); console.log('Owner is now:', myClass.teacherEmail); // Should match your email after acceptance -
Clear Browser Cache
Settings → Privacy → Clear browsing data → Cached images and files
Enrollment Code Issues
Problem: Students Can't Enroll with Code
Common Causes
-
Typo in Code
- Enrollment codes are case-sensitive
- Format:
ENROLL-ABC12345(8 characters after dash) - Solution: Copy-paste the code instead of typing
-
Code Changed
- Owner may have regenerated the enrollment code
- Solution: Get updated code from teacher
-
Class Archived
- Archived classes don't accept new enrollments
- Solution: Contact class owner to restore class
Problem: Need to Regenerate Enrollment Code
Scenario: Enrollment code was shared publicly by mistake.
Via UI
- Open class details modal
- Click "Edit" button
- Change enrollment code field to a new value
- Click "Save"
- Share new code with legitimate students only
Via API
await fetch(`/api/school/class/${classId}`, {
method: 'PATCH',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
enrollmentCode: 'ENROLL-NEWCODE1'
})
});
xAPI LRS Connection Issues
Problem: Classes Not Loading
Debugging Steps
Check Server Logs
Look for xAPI connection errors in server console:
// Common error messages:
"Failed to connect to LRS"
"LRS authentication failed"
"xAPI statement retrieval timeout"
Verify LRS Configuration
Check environment variables are set correctly:
LRS_ENDPOINT=https://your-lrs.com/xapi
LRS_USERNAME=your_username
LRS_PASSWORD=your_password
Test LRS Connection
// Run health check
npm run health:quick
// Or test xAPI specifically
npm run test:xapi
Check LRS Statement Retrieval
Verify statements are being retrieved correctly:
// In xapiClient.js, check query filters
const result = await this.getStatements({
agent: { mbox: `mailto:${userEmail}`, objectType: 'Agent' },
verb: 'http://adlnet.gov/expapi/verbs/initialized',
activity: 'https://uals.app/class/',
related_activities: true
});
// Ensure not using getAllStatements() (deprecated)
Problem: Duplicate Classes Appearing
Root Cause
Multiple xAPI statements exist for the same class ID due to updates.
The getAllClasses() function should deduplicate by keeping
only the most recent statement per class ID.
Solution
// In schoolData.js, ensure deduplication logic:
const classMap = new Map();
statements.forEach(stmt => {
const classId = stmt.context.extensions['http://uals.app/class/id'];
const existing = classMap.get(classId);
// Keep newest statement
if (!existing || new Date(stmt.timestamp) > new Date(existing.timestamp)) {
classMap.set(classId, stmt);
}
});
const uniqueClasses = Array.from(classMap.values());
Browser-Specific Issues
Safari: Cookie Restrictions
Solution
- Safari → Preferences → Privacy
- Uncheck "Prevent cross-site tracking"
- OR add exception for uals.app domain
- Refresh UALS dashboard
Chrome: Incognito Mode
Solution
- Chrome → Settings → Privacy and security → Cookies
- Select "Allow all cookies" or add exception for uals.app
- Alternatively, use normal mode instead of incognito
Firefox: Enhanced Tracking Protection
Solution
- Click shield icon in address bar
- Toggle "Enhanced Tracking Protection" to OFF for uals.app
- Refresh page
Developer Debugging Tools
Browser Console Utilities
// Check authentication status
const user = await UALS_Auth.getUser();
console.log('User:', user);
// Fetch all classes
const classes = await fetch('/api/school/classes', {
credentials: 'include'
}).then(r => r.json());
console.log('Classes:', classes);
// Check specific class ownership
const myClass = classes.classes.find(c => c.id === 'class-xxx');
console.log('Owner:', myClass.teacherEmail);
console.log('Creator:', myClass.creatorEmail);
console.log('Experts:', myClass.contentExperts);
// Verify you can edit
const canEdit = myClass.teacherEmail === user.email ||
myClass.contentExperts.includes(user.email);
console.log('Can edit:', canEdit);
// Check pending transfers
classes.classes.forEach(c => {
if (c.ownershipTransferPending) {
console.log('Pending transfer:', c.id, JSON.parse(c.ownershipTransferPending));
}
});
Server-Side Debugging
// In canEditClassContent() function:
async function canEditClassContent(userEmail, classId) {
console.log(`🔍 Permission check: user=${userEmail}, class=${classId}`);
const classData = await getClassData(classId);
console.log(`📋 Class data:`, {
owner: classData.teacherEmail,
creator: classData.creatorEmail,
experts: classData.contentExperts
});
const isOwner = classData.teacherEmail === userEmail;
const isExpert = classData.contentExperts?.includes(userEmail);
console.log(`✅ isOwner=${isOwner}, isExpert=${isExpert}`);
return isOwner || isExpert;
}
Health Check Commands
# Full health check (LLM, LRS, GCS)
npm run health
# Quick health check
npm run health:quick
# Test specific components
npm run test:xapi
npm run test:gcs
npm run test:openai
Getting Help
Gather the following information to expedite troubleshooting:
- Your user email and role
- Class ID experiencing the issue
- Exact error message or unexpected behavior
- Browser and version (e.g., Chrome 120.0)
- Steps to reproduce the issue
- Screenshots of error messages
- Browser console logs (F12 → Console tab)
- Network requests (F12 → Network tab, filter by "school" or "class")
Support Channels
Email Support
Contact UALS technical support with detailed issue description and debugging information gathered above.
Documentation
Review the complete documentation including API reference, user roles guide, and this troubleshooting page.
View DocsBug Reports
File bug reports with reproducible steps, expected vs actual behavior, and system information.
Community Forum
Search for similar issues or ask questions in the UALS educator community forum (if available).