1// core/error-handling.js â extracted from app.js (lines 12008-12062). 2// Classic script: shares the global scope with every other core/ and features/ 3// script. Do NOT wrap in an IIFE and do NOT convert to an ES module â top-level 4// function declarations must attach to window for inline on* handlers, and 5// top-level const/let are shared across files. 6 7function showGlobalError(message) { 8 const overlay = document.getElementById('globalError'); 9 const msgEl = document.getElementById('globalErrorMessage'); 10 if (overlay && msgEl) { 11 msgEl.textContent = message || 'The application encountered a critical error and could not continue.'; 12 overlay.classList.remove('hidden'); 13 } else { 14 console.error('CRITICAL ERROR (No UI):', message); 15 alert('CRITICAL ERROR: ' + message); 16 } 17} 18 19window.onerror = function(message, source, lineno, colno, error) { 20 // We don't want to show the global error for EVERY script error (some might be minor) 21 // but we should definitely log it. 22 console.error('[Global Error]', { message, source, lineno, colno, error }); 23 24 // If the error happens during the first 2 seconds, it's likely a boot error 25 if (performance.now() < 2000) { 26 showGlobalError('Failed to initialize the application. A script error occurred during startup.'); 27 } 28}; 29 30// A missing/expired token drops the user straight to the login screen â 31// no toasts or alerts (standing rule 2026-09-02). Idempotent so a burst of 32// parallel 401s only switches screens once. 33let sessionExpiredHandled = false; 34window.handleSessionExpired = () => { 35 if (sessionExpiredHandled) return; 36 sessionExpiredHandled = true; 37 try { clearSession(); } catch (_e) { /* already cleared */ } 38 showAuth(); 39 setAuthMode('login'); 40 setTimeout(() => { sessionExpiredHandled = false; }, 1500); 41}; 42 43window.onunhandledrejection = function(event) { 44 console.error('[Unhandled Rejection]', event.reason); 45 46 const reason = event.reason || {}; 47 const message = reason.message || 'An unexpected error occurred.'; 48 49 if (reason.isNetworkError) { 50 showToast(message, 'error'); 51 } else if (reason.status === 401) { 52 // Token expired or invalid â go straight to login, no message. 53 if (state.token) handleSessionExpired(); 54 } else { 55 showToast(message, 'error'); 56 } 57}; 58 59window.clearAndReload = () => { 60 if (confirm('This will clear all local settings and log you out. Continue?')) { 61 localStorage.clear(); 62 window.location.reload(); 63 } 64}; 65 66// Check for offline status 67window.addEventListener('online', () => showToast('Back online!', 'success')); 68window.addEventListener('offline', () => showToast('Connection lost. Working offline.', 'warning'));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.