Troubleshooting
Reproduce a discard
Section titled “Reproduce a discard”- Open a normal website tab and let it fully load.
- Switch to another tab and wait a couple of seconds, so the scheduled captures can run.
- Discard the first tab: open
chrome://discards, find the tab, click Urgent Discard. - Switch back to it and watch what happens.
Collect a trace
Section titled “Collect a trace”- Set
DEBUG_LOGS = truein bothbackground.jsandcontent.js. - Reload the extension on
chrome://extensions. - Under Better Tab Unload, click the Service worker link in Inspect views.
- Keep that console open while you reproduce the problem. Content-script and interstitial events are forwarded here too, so this one console shows the whole flow.
- If you need to save the output, right-click the console and use Save as… into the
repository’s gitignored
logs/directory, for examplelogs/restore-trace.log.
Expected happy-path event order
Section titled “Expected happy-path event order”With both debug flags on, a successful interstitial restore looks like this:
onUpdated:discarded-truemarkDiscardedReloadprepareRestoreScreenshot:loadedrestoreInterstitial:shownCS:restore:startGET_RESTORE_INTERSTITIAL_DATA:replywithhasScreenshot: trueCS:restore:screenshot-hitCS:restore:navigate- Target page
onUpdatedtoloading, thencomplete REQUEST_SCREENSHOT_OVERLAY:skip-after-restore-interstitial— confirming no second placeholder was drawn
Useful greps
Section titled “Useful greps”Run these against a log you saved in logs/:
# restore flowgrep -n "restoreInterstitial\|CS:restore\|GET_RESTORE_INTERSTITIAL_DATA\|REQUEST_SCREENSHOT_OVERLAY" logs/*.log# teardowngrep -n "onUpdated:complete\|hideOverlayInTab\|overlay-removed\|message-hide" logs/*.log# anything the state machine refused to dogrep -n "send-failed\|timeout\|skip" logs/*.logSymptom checklist
Section titled “Symptom checklist”The placeholder never appears
Section titled “The placeholder never appears”- Compare
prepareRestoreScreenshot:loadedagainstprepareRestoreScreenshot:missing. Amissingmeans no screenshot was ever stored for that URL. - Open the options page and check whether a screenshot for that URL exists at all. If not,
the capture side is the problem, not the restore side: the tab may never have been active
and
completelong enough, or its URL is inSKIP_URL_PATTERNS. - Look for
captureAndStore:failed. Chrome rate-limitscaptureVisibleTab, and captures are also refused for minimized windows.
The placeholder appears too late
Section titled “The placeholder appears too late”- Many
pushOverlayToTab:send-failedentries before the firstCS:request-overlaymean the content script was not ready yet, so the overlay fallback lost the race. - Check whether
restoreInterstitial:shownis present. If it is missing, the fast path did not run — look for the reason:skip-inactive-tab,skip-url-mismatch, orskip-target-already-complete.
The placeholder stays on screen
Section titled “The placeholder stays on screen”- Confirm
onUpdated:completefires for the target URL. - Confirm
message-hideandoverlay-removedboth appear. Ifmessage-hideis missing, all threeHIDE_SCREENSHOT_OVERLAYattempts failed. - Worst case the safety timers in
content.jsclear it after 6 and 12 seconds; seeingoverlay-safety-timeoutmeans normal teardown did not happen.
A restored tab lands on the wrong page
Section titled “A restored tab lands on the wrong page”This is the stale-URL failure mode described in
How It Works. Look for skip-url-mismatch,
skip-pending-navigation, and skip-tab-being-restored: those guards preventing a
navigation is the correct behaviour. If a tab genuinely ends up on a previous history entry,
capture the markDiscardedReload and restoreInterstitial:shown lines with their
currentUrl and targetUrl values — that pair identifies which guard was missing.
Reset state
Section titled “Reset state”- Open the options page and click Clear All.
- Reload the extension from
chrome://extensions. - Re-run the repro to capture a clean trace.