Files
2026-07-12 10:17:17 -04:00

2.5 KiB

Silent setTimeout / Async Callback Errors

Session Context

Debugged in ShopProQuote (PocketBase web app) — "Mark as Completed" flow on repair orders.

The Bug

Clicking work-status-badge → "Completed" → confirm modal → nothing. Financial summary modal never appeared. No console errors.

The Chain

  1. User clicks confirm button in dynamically-created confirm modal element
  2. Click handler calls updateRepairOrderWorkStatus(roId, 'completed') (async)
  3. Inside, code reaches if (newWorkStatus === 'completed') branch (confirmed by console.log)
  4. setTimeout(() => { openFinancialSummaryModal(roId); }, 100) is scheduled
  5. return exits both the function and the enclosing try/catch
  6. 100ms later, openFinancialSummaryModal runs — this is NOW outside any try/catch
  7. Line 1545: document.getElementById('financial-customer-name').textContent = ...
  8. #financial-customer-name never existed in the HTML → null.textContentTypeError
  9. The TypeError is uncaught (no try/catch in the detached context) → global error handler
  10. Global error handler does nothing visible → user sees "nothing happens"

The Tool That Caught It

Overriding window.setTimeout from Playwright:

page.evaluate("""()=>{
    window.__origSetTimeout = window.setTimeout.bind(window);
    window.setTimeout = function(fn, delay) {
        if(delay===100) {
            return window.__origSetTimeout(function(){
                try { return fn(); }
                catch(e) { console.error('TIMEOUT ERROR:', e); }
            }, delay);
        }
        return window.__origSetTimeout(fn, delay);
    };
}""")

This logged: TIMEOUT ERROR: TypeError: Cannot set properties of null (setting 'textContent') at openFinancialSummaryModal (repair-orders.js:1545:72)

The Fix

Added missing <span id="financial-customer-name">--</span> to the financial-summary-modal HTML in repair-orders.html.

Verification Pattern

After the fix, the full keyboard+click flow was re-tested end-to-end via Playwright:

  1. Create repair order (fill form)
  2. Click work status badge → select "Completed"
  3. Confirm modal → financial modal appears
  4. Fill CP Total / CP Cost
  5. Click "Complete" → modal closes, notification shows

One way to overwrite for robust test runs:

# Trap ALL setTimeout errors during test
page.evaluate("""()=>{
    const _st=window.setTimeout.bind(window);
    window.setTimeout=(fn,d)=>_st(function(){
        try{return fn()}catch(e){console.error('setTimeout ERROR:',e.stack||e)}
    },d);
}""")