pbakaus/impeccable · error · Error
errBody.error || ('HTTP ' + res.status)
Error message
errBody.error || ('HTTP ' + res.status) What it means
The live-mode in-page script POSTs pending copy edits to the local dev server (/...stash endpoint) and, on a non-OK HTTP response, throws Error(errBody.error || 'HTTP <status>'). The message is either the server's JSON error field or a bare status code if the body is not JSON.
Source
Thrown at skill/scripts/live-browser.js:3801
if (container) for (const op of ops) op.container = container;
try {
// Token in the query string as well as the body: the URL token is what
// authorizes the CORS preflight when the page runs on a non-loopback
// dev host (ddev, Valet), since the preflight carries no request body.
const res = await fetch('http://localhost:' + PORT + '/manual-edit-stash?token=' + encodeURIComponent(TOKEN), {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
token: TOKEN,
id: id8(),
pageUrl: location.pathname,
element: extractContext(contextElement),
ops,
}),
});
if (!res.ok) {
const errBody = await res.json().catch(() => ({}));
throw new Error(errBody.error || ('HTTP ' + res.status));
}
const stashResult = await res.json();
updatePendingCounter(stashResult.pendingCount || 0);
maybeShowFirstSaveToast();
disableInlineEdit();
setLiveState('CONFIGURING');
showBar('configure');
showAnnotOverlay(selectedElement);
renderEditBadge('idle');
} catch (err) {
console.error('[impeccable] manual edit stash failed:', err);
const detail = String(err?.message || '');
if (detail.includes('newText cannot contain') || detail.includes('newText cannot be empty')) {
showToast('Save rejected: ' + detail.replace(/^manual_edits:\s*/, ''), 5500);
} else {
showToast('Save failed - retry or cancel', 4000);
}
}View on GitHub (pinned to 2bc2879276)
Solutions
- Check the thrown message and the dev-server console for the underlying error field
- Verify the dev server is running on the expected PORT and the page TOKEN matches the current session
- Refresh the page to re-handshake token/state, then re-apply the edit
- If the status is 5xx, inspect server logs for the failing request handler
Example fix
// caller hardening
try {
await stashEdits(ops);
} catch (e) {
showToast('Save failed: ' + e.message + ' - is the dev server running?', 4000);
} Defensive patterns
Strategy: try-catch
Validate before calling
async function devServerReachable(port) {
try { const r = await fetch('http://localhost:' + port + '/health'); return r.ok; }
catch { return false; }
}
// check before attempting the stash POST Try / catch
try {
const res = await fetch(stashUrl, { method: 'POST', body });
if (!res.ok) {
const errBody = await res.json().catch(() => ({}));
throw new Error(errBody.error || ('HTTP ' + res.status));
}
} catch (e) {
showToast('Save failed: ' + e.message, 4000); // and keep edits pending locally
} Prevention
- Verify the dev server is up and the token matches before enabling live edit
- Refresh the page after any server restart to re-handshake
- Surface the thrown message in the UI instead of swallowing it
- Keep edits staged locally until the server confirms success
When it happens
Trigger: Saving edits while the local impeccable dev-server returns 4xx/5xx, is down, or responds with a non-JSON error body.
Common situations: Dev server restarted with a different token/port; server rejected the edit payload (validation); proxy or firewall intercepting localhost requests.
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
- HTTP ${res.status}
- ${String(res.status)}
- source read failed: ${r.status}
- ${r.status}
- TypeError: fetch failed: {}
AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08).
Data as JSON: /api/errors/e25910a5f0fdb00f.
Report an issue: GitHub.