jackwener/OpenCLI · warning

[opencli] Navigate to ${targetUrl} timed out after 15s

Error message

[opencli] Navigate to ${targetUrl} timed out after 15s

What it means

A console warning from the navigation wait helper: when a target page's load/complete event does not fire within 15 seconds, the extension logs this, marks the wait as timed out, and proceeds (finish()) rather than hanging forever. The subsequent command may operate on a partially loaded page.

Source

Thrown at extension/src/background.ts:1799

        finish();
      }
    };
    chrome.tabs.onUpdated.addListener(listener);

    // Also check if the tab already navigated (e.g. instant cache hit)
    checkTimer = setTimeout(async () => {
      try {
        const currentTab = await chrome.tabs.get(tabId);
        if (currentTab.status === 'complete' && isNavigationDone(currentTab.url)) {
          finish();
        }
      } catch { /* tab gone */ }
    }, 100);

    // Timeout fallback with warning
    timeoutTimer = setTimeout(() => {
      timedOut = true;
      console.warn(`[opencli] Navigate to ${targetUrl} timed out after 15s`);
      finish();
    }, 15000);
  });

  let tab = await chrome.tabs.get(tabId);

  // Post-navigation drift detection: if the tab moved to another window
  // during navigation (e.g. a tab-management extension regrouped it),
  // try to move it back to maintain session isolation.
  const postNavigationSession = automationSessions.get(leaseKey);
  if (postNavigationSession && tab.windowId !== postNavigationSession.windowId) {
    console.warn(`[opencli] Tab ${tabId} drifted to window ${tab.windowId} during navigation, moving back to ${postNavigationSession.windowId}`);
    try {
      await chrome.tabs.move(tabId, { windowId: postNavigationSession.windowId, index: -1 });
      tab = await chrome.tabs.get(tabId);
    } catch (moveErr) {
      console.warn(`[opencli] Failed to recover drifted tab: ${moveErr}`);
    }

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — transient network slowness often resolves
  2. Verify the target URL is reachable in a normal browser tab
  3. Check proxy/VPN/captive-portal state blocking page load
  4. Increase the navigation timeout in background.ts if 15s is too short for the target site

Example fix

// before
timeoutTimer = setTimeout(() => { ... finish(); }, 15000);
// after
timeoutTimer = setTimeout(() => { ... finish(); }, 30000); // tolerate slow sites
Defensive patterns

Strategy: try-catch

Validate before calling

const reachable = await fetch(targetUrl, { method: 'HEAD', mode: 'no-cors', signal: AbortSignal.timeout(5000) }).then(r => r.ok).catch(() => false);
if (!reachable) warnUserBeforeNavigate();

Try / catch

const ok = await navigateAndWait(tabId, url, 15000).catch(() => false);
if (!ok) console.warn('page may be partially loaded');

Prevention

When it happens

Trigger: chrome.tabs.update/get navigation to targetUrl where the load event never completes within 15000ms — slow site, hung network request, or a page whose lifecycle events don't map to the awaited condition.

Common situations: Slow or unresponsive target websites; captive portals or proxy auth prompts blocking load; SPAs with long-polling connections that keep the page 'loading'; offline/broken network during automation.

Understand the failure class

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/5b3f9fe366c1936e. Report an issue: GitHub.