(() => { if (typeof window === 'undefined') { return; } if (window.__tenantpilotUnhandledRejectionLoggerApplied) { return; } window.__tenantpilotUnhandledRejectionLoggerApplied = true; const recentKeys = new Map(); const cleanupRecentKeys = (nowMs) => { for (const [key, timestampMs] of recentKeys.entries()) { if (nowMs - timestampMs > 5_000) { recentKeys.delete(key); } } }; const isTransportEnvelope = (value) => { return value !== null && typeof value === 'object' && Object.prototype.hasOwnProperty.call(value, 'status') && Object.prototype.hasOwnProperty.call(value, 'body') && Object.prototype.hasOwnProperty.call(value, 'json') && Object.prototype.hasOwnProperty.call(value, 'errors'); }; const isCancellationReason = (reason) => { if (!isTransportEnvelope(reason)) { return false; } return reason.status === null && reason.body === null && reason.json === null && reason.errors === null; }; const isPageHiddenOrInactive = () => { if (document.visibilityState !== 'visible') { return true; } return typeof document.hasFocus === 'function' ? document.hasFocus() === false : false; }; const isExpectedBackgroundTransportFailure = (reason) => { if (isCancellationReason(reason)) { return true; } if (!isTransportEnvelope(reason) || !isPageHiddenOrInactive()) { return false; } return (reason.status === 419 && typeof reason.body === 'string' && reason.body.includes('Page Expired')) || (reason.status === 404 && typeof reason.body === 'string' && reason.body.includes('Not Found')); }; const normalizeReason = (value, depth = 0) => { if (depth > 3) { return '[max-depth-reached]'; } if (value instanceof Error) { return { type: 'Error', name: value.name, message: value.message, stack: value.stack, }; } if (value === null || value === undefined) { return value; } if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') { return value; } if (Array.isArray(value)) { return value.slice(0, 10).map((item) => normalizeReason(item, depth + 1)); } if (typeof value === 'object') { const result = {}; const allowedKeys = [ 'message', 'stack', 'name', 'type', 'status', 'body', 'json', 'errors', 'reason', 'code', ]; for (const key of allowedKeys) { if (Object.prototype.hasOwnProperty.call(value, key)) { result[key] = normalizeReason(value[key], depth + 1); } } if (Object.keys(result).length > 0) { return result; } const stringTag = Object.prototype.toString.call(value); return { type: stringTag, value: String(value), }; } return String(value); }; const toStableJson = (payload) => { try { return JSON.stringify(payload); } catch { return JSON.stringify({ source: payload.source, href: payload.href, timestamp: payload.timestamp, reason: '[unserializable]', }); } }; window.addEventListener('unhandledrejection', (event) => { const normalizedReason = normalizeReason(event.reason); const payload = { source: 'window.unhandledrejection', href: window.location.href, timestamp: new Date().toISOString(), reason: normalizedReason, }; if (isExpectedBackgroundTransportFailure(normalizedReason)) { event.preventDefault(); return; } const dedupeKey = toStableJson({ source: payload.source, href: payload.href, reason: payload.reason, }); const payloadJson = toStableJson(payload); const nowMs = Date.now(); cleanupRecentKeys(nowMs); if (recentKeys.has(dedupeKey)) { return; } recentKeys.set(dedupeKey, nowMs); console.error(`TenantPilot unhandled promise rejection ${payloadJson}`); }); })();