pbakaus/impeccable · error · Error

HTTP ${res.status}

Error message

HTTP ${res.status}

What it means

Discarding manual edits POSTs to /manual-edit-discard; on a non-OK response the code throws Error('HTTP ' + res.status). Unlike the commit paths, this one does not parse the response body for a server error message, so you only get the status code.

Source

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

    } finally {
      if (waitForSseCompletion) return;
      const remainingCount = parseInt(pendingPillEl?.dataset.count || '0', 10) || 0;
      if (remainingCount > 0) setPendingApplyLoading(false);
      else hidePendingApplyDock();
    }
  }

  async function onPendingTrashClick() {
    const count = parseInt(pendingPillEl?.dataset.count || '0', 10);
    if (count <= 0 || pendingApplyInFlight) return;
    const ok = confirm('Discard ' + count + ' copy edit' + (count === 1 ? '' : 's') + ' on this page?');
    if (!ok) return;
    try {
      const res = await fetch(
        'http://localhost:' + PORT + '/manual-edit-discard?token=' + encodeURIComponent(TOKEN) + '&pageUrl=' + encodeURIComponent(location.pathname),
        { method: 'POST' },
      );
      if (!res.ok) throw new Error('HTTP ' + res.status);
      const result = await res.json().catch(() => ({}));
      const restoreFailures = restoreDiscardedManualEdits(result.entries || []);
      updatePendingCounter(0);
      if (restoreFailures > 0) {
        showToast('Discarded ' + count + ' copy edit' + (count === 1 ? '' : 's') + ' - refresh to reset ' + restoreFailures, 4000);
      } else {
        showToast('Discarded ' + count + ' copy edit' + (count === 1 ? '' : 's'), 2500);
      }
    } catch (err) {
      console.error('[impeccable] discard failed:', err);
      showToast('Discard failed - see console', 4000);
    }
  }

  function showManualApplyDecision(msg) {
    const count = parseInt(pendingPillEl?.dataset.count || '0', 10) || numberOrNull(msg?.remainingCount) || 0;
    pendingApplyInFlight = false;
    storeManualApplyState(count, {

View on GitHub (pinned to 2bc2879276)

Solutions

  1. Note the status: 401/403 implies token mismatch — refresh the page to re-handshake
  2. Check the dev-server logs for the /manual-edit-discard request failure
  3. Retry the discard after refreshing; edits remain applied so nothing is lost
  4. Re-run the live session if the server state has diverged

Example fix

// before
if (!res.ok) throw new Error('HTTP ' + res.status);
// after
if (!res.ok) {
  const errBody = await res.json().catch(() => ({}));
  throw new Error(errBody.error || ('HTTP ' + res.status));
}
Defensive patterns

Strategy: try-catch

Validate before calling

async function discardIsSafe(port, token, pageUrl) {
  const res = await fetch('http://localhost:' + port + '/state?token=' + token);
  return res.ok; // server session alive before discarding
}

Try / catch

try {
  const res = await fetch(discardUrl, { method: 'POST' });
  if (!res.ok) throw new Error('HTTP ' + res.status);
} catch (e) {
  showToast('Discard failed: ' + e.message + ' - refresh to re-sync', 4000);
}

Prevention

When it happens

Trigger: Clicking discard (trash) on pending copy edits while the dev server returns 4xx/5xx — e.g. stale token or unknown pageUrl.

Common situations: Dev server restarted (token mismatch); the pending-edit list changed server-side; transient server error during teardown.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08). Data as JSON: /api/errors/d1f29ee8f77bdc58. Report an issue: GitHub.