Cover by ChatGPT Images 2.0 using just this text (below)

PROMPT: Here are two URLs that seem to trip up the tab cycler. It switches to waiting even though these sites have loaded. Can you take a look at these URLs and let me know why the Chrome extension gets stuck on them? https://www.msn.com/en-us/money/general/openai-launches-10b-ai-venture-backed-by-tpg-bain-softbank-bloomberg/ar-AA22miSj?utm_source=substack&utm_medium=email https://www.theverge.com/ai-artificial-intelligence/925338/openai-musk-v-altman-mira-murati

RESPONSE FROM CLAUDE:
Let me look at these URLs in the browser to see what state they end up in.

Found the issue. Here’s what’s happening:

Root cause: the tab.status === "complete" gate

In background.js:102, checkTabContent short-circuits to “not ready” whenever tab.status !== "complete":

if (tab.status !== "complete") return false;

tab.status is "complete" only after the browser fires the load event — i.e., after every subresource (ads, trackers, analytics beacons, lazy iframes, video preloads) has finished or errored out.

Both URLs you sent are on sites with extremely heavy third-party ad/tracker stacks:

  • MSN loads dozens of ad-tech scripts (Microsoft Advertising, Taboola/Outbrain‑style modules, telemetry beacons). On article pages the load event commonly doesn’t fire for 20–60+ seconds, and sometimes never within a normal session.
  • The Verge (Vox Media’s Concert ad stack) is similarly heavy — Permutive, Kargo, GAM, video preloads, etc., often keeping the page in loading state long after the article is fully visible and readable.

So the cycler does this:

  1. tab.status is still "loading" after your 1‑second delay → checkTabContent returns false.
  2. retryCount 0 → reload + 5s buffer.
  3. Reload restarts the whole ad waterfall → still "loading" after 5s → retryCount 1 fails again → flips to WAIT for 5 minutes.

Meanwhile the article (title, h1, body) has been visible the whole time — I confirmed on MSN: document.readyState was already "complete" and the title was the full article headline, but chrome.tabs.get(...).status lags behind that for ad-heavy pages.

The Twitter case you originally tuned for is the opposite problem (DOM not ready yet), which is why the gate is there — but it punishes any site whose load event is gated on slow ad networks.

Suggested fixes (pick one)

  1. Drop the tab.status precondition and rely on the in-page check alone. The injected function already runs in the page and checks document.title directly; if it returns truthy, you don’t care whether ad beacons are still in flight.
  2. Use document.readyState instead of tab.status: inside the injected func, return false only if document.readyState === 'loading'. interactive and complete both mean the DOM is parsed, which is what you actually want.
  3. Allowlist domains where load is unreliable (msn.com, theverge.com, vox.com, cnn.com, nytimes.com, etc.) and skip the tab.status gate for them.

Option 1 is the cleanest — the title/DOM check is already the real signal. Want me to make the change?

Leave a Reply

Trending

Discover more from Ethan B. Holland

Subscribe now to keep reading and get access to the full archive.

Continue reading