pbakaus/impeccable · warning

[impeccable] failed to fetch pending count:

Error message

[impeccable] failed to fetch pending count:

What it means

The on-page client polls GET /manual-edit-stash?token=...&pageUrl=... on the local live server to keep the pending-edits pill count current. Any network-level rejection of that fetch (server not listening, wrong port, connection reset) is caught and logged as 'failed to fetch pending count:'; the pill simply keeps its last known count. Note a 401 does not produce this log — !res.ok returns silently.

Source

Thrown at skill/scripts/live-browser.js:4090

    if (previousCount <= 0) playPendingIntroAnimation();
  }

  function maybeShowFirstSaveToast() {
    if (!firstSaveOfSession) return;
    firstSaveOfSession = false;
    showToast('Saved. Click "Apply copy edits" to write changes.', 4500);
  }

  async function fetchPendingCount() {
    try {
      const res = await fetch(
        'http://localhost:' + PORT + '/manual-edit-stash?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname),
      );
      if (!res.ok) return;
      const data = await res.json();
      updatePendingCounter(data.count || 0);
    } catch (err) {
      console.warn('[impeccable] failed to fetch pending count:', err);
    }
  }

  async function onPendingPillClick() {
    const count = parseInt(pendingPillEl?.dataset.count || '0', 10);
    if (count <= 0 || pendingApplyInFlight) return;
    const ok = confirm('Apply ' + count + ' copy edit' + (count === 1 ? '' : 's') + ' to source?');
    if (!ok) return;
    let waitForSseCompletion = false;
    resetManualApplyProgress(count);
    setPendingApplyLoading(true, count);
    try {
      const res = await fetch(
        'http://localhost:' + PORT + '/manual-edit-commit?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname) + '&async=1',
        { method: 'POST', keepalive: true },
      );
      if (!res.ok) {
        const errBody = await res.json().catch(() => ({}));

View on GitHub (pinned to f88b2837a7)

Solutions

  1. Restart the live server (the impeccable serve/dev command) and reload the page so PORT and TOKEN refresh
  2. Confirm the port the page is fetching matches the running server's output
  3. Set NO_PROXY=localhost,127.0.0.1 if a system proxy intercepts loopback fetches
Defensive patterns

Strategy: retry

Validate before calling

// Health-check the server before relying on pending-count polling
const ok = await fetch(`http://localhost:${PORT}/status?token=${encodeURIComponent(TOKEN)}`).then((r) => r.ok).catch(() => false);
if (!ok) { promptServerRestart(); return; }

Try / catch

try { /* fetch pending count */ } catch (err) { console.warn(err); /* keep last count; next poll interval retries */ }

Prevention

When it happens

Trigger: The live server was stopped or crashed; the page holds a stale PORT after the server moved; a proxy or firewall intercepts localhost requests; the machine's loopback is unavailable.

Common situations: Dev server exited while its injected page stayed open; server restarted on a different port and the old tab still polls the dead one; corporate proxy env vars routing localhost through a proxy.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18). Data as JSON: /api/errors/d9c6554a8ac4d3b8. Report an issue: GitHub.