{"record":{"id":"e25910a5f0fdb00f","repo":"pbakaus/impeccable","slug":"errbody-error-http-res-status-e25910","errorCode":null,"errorMessage":"errBody.error || ('HTTP ' + res.status)","messagePattern":"errBody\\.error \\|\\| \\('HTTP ' \\+ res\\.status\\)","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skill/scripts/live-browser.js","lineNumber":3801,"sourceCode":"    if (container) for (const op of ops) op.container = container;\n    try {\n      // Token in the query string as well as the body: the URL token is what\n      // authorizes the CORS preflight when the page runs on a non-loopback\n      // dev host (ddev, Valet), since the preflight carries no request body.\n      const res = await fetch('http://localhost:' + PORT + '/manual-edit-stash?token=' + encodeURIComponent(TOKEN), {\n        method: 'POST',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({\n          token: TOKEN,\n          id: id8(),\n          pageUrl: location.pathname,\n          element: extractContext(contextElement),\n          ops,\n        }),\n      });\n      if (!res.ok) {\n        const errBody = await res.json().catch(() => ({}));\n        throw new Error(errBody.error || ('HTTP ' + res.status));\n      }\n      const stashResult = await res.json();\n      updatePendingCounter(stashResult.pendingCount || 0);\n      maybeShowFirstSaveToast();\n      disableInlineEdit();\n      setLiveState('CONFIGURING');\n      showBar('configure');\n      showAnnotOverlay(selectedElement);\n      renderEditBadge('idle');\n    } catch (err) {\n      console.error('[impeccable] manual edit stash failed:', err);\n      const detail = String(err?.message || '');\n      if (detail.includes('newText cannot contain') || detail.includes('newText cannot be empty')) {\n        showToast('Save rejected: ' + detail.replace(/^manual_edits:\\s*/, ''), 5500);\n      } else {\n        showToast('Save failed - retry or cancel', 4000);\n      }\n    }","sourceCodeStart":3783,"sourceCodeEnd":3819,"githubUrl":"https://github.com/pbakaus/impeccable/blob/2bc2879276c1f321a53c4ca99d3371e411329b52/skill/scripts/live-browser.js#L3783-L3819","documentation":"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.","triggerScenarios":"Saving edits while the local impeccable dev-server returns 4xx/5xx, is down, or responds with a non-JSON error body.","commonSituations":"Dev server restarted with a different token/port; server rejected the edit payload (validation); proxy or firewall intercepting localhost requests.","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"],"exampleFix":"// caller hardening\ntry {\n  await stashEdits(ops);\n} catch (e) {\n  showToast('Save failed: ' + e.message + ' - is the dev server running?', 4000);\n}","handlingStrategy":"try-catch","validationCode":"async function devServerReachable(port) {\n  try { const r = await fetch('http://localhost:' + port + '/health'); return r.ok; }\n  catch { return false; }\n}\n// check before attempting the stash POST","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(stashUrl, { method: 'POST', body });\n  if (!res.ok) {\n    const errBody = await res.json().catch(() => ({}));\n    throw new Error(errBody.error || ('HTTP ' + res.status));\n  }\n} catch (e) {\n  showToast('Save failed: ' + e.message, 4000); // and keep edits pending locally\n}","preventionTips":["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"],"tags":["http","fetch","dev-server"],"backgroundTag":"http-error-response","analyzedSha":"2bc2879276c1f321a53c4ca99d3371e411329b52","analyzedAt":"2026-09-08T04:51:14.109Z","contentChangedAt":"2026-09-08T04:51:14.109Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}