{"record":{"id":"7c911f486309b0bd","repo":"odysseus-dev/odysseus","slug":"res-statustext-string-res-status","errorCode":null,"errorMessage":"res.statusText || String(res.status)","messagePattern":"res\\.statusText \\|\\| String\\(res\\.status\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/document.js","lineNumber":1061,"sourceCode":"    if (!prev) return false;\n    _pdfUndoStackByDoc.set(docId, stack);\n    if (_pdfPaneSaveTimer) {\n      clearTimeout(_pdfPaneSaveTimer);\n      _pdfPaneSaveTimer = null;\n    }\n    const doc = docs.get(docId);\n    if (!doc) return false;\n    doc.content = prev;\n    const ta = document.getElementById('doc-editor-textarea');\n    if (ta) ta.value = prev;\n    _setPdfSaveStatus('saving');\n    try {\n      const res = await fetch(`${API_BASE}/api/document/${docId}`, {\n        method: 'PUT',\n        headers: { 'Content-Type': 'application/json' },\n        body: JSON.stringify({ content: prev }),\n      });\n      if (!res.ok) throw new Error(res.statusText || String(res.status));\n      _setPdfSaveStatus('saved');\n      _renderPdfPane();\n      return true;\n    } catch (e) {\n      _setPdfSaveStatus('error', e.message || 'Undo failed');\n      return true;\n    }\n  }\n\n  // Active drop mode for the PDF toolbar — toolbar buttons set this; the\n  // next click on a page consumes it. null means clicks do nothing.\n  let _pdfDropMode = null;\n  // Per-doc last-used line spacing for text annotations. Once the user picks\n  // 1.6 for one box, every text box dropped after that defaults to 1.6.\n  const _pdfLastLineHeight = new Map(); // docId -> number\n  function _setPdfDropMode(mode) {\n    _pdfDropMode = mode;\n    const pane = document.getElementById('doc-pdf-view');","sourceCodeStart":1043,"sourceCodeEnd":1079,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/document.js#L1043-L1079","documentation":"Error thrown during undo-save of a PDF-linked document: PUT /api/document/{docId} with the previous content returned non-OK. Only statusText or the numeric status is used — the body is ignored, so the reason is usually vague (and many proxies send empty statusText). The UI then sets the save pill to 'error' with the undo-failed message.","triggerScenarios":"PUT /api/document/{id} returns 404 (doc deleted elsewhere), 409 (optimistic-concurrency conflict), 413 (content grew beyond a body limit), 500 (storage write failure).","commonSituations":"Document deleted in another tab/session while this one held an old copy; disk full on the server; proxy body-size limit exceeded after pasting large content into the editor; empty statusText making the message just '500'.","solutions":["curl -i -X PUT the same JSON to see the status and body the code drops","Reload the session/document list to resync docId state if 404/409","Free server disk / check write permissions for 500s","Raise proxy client_max_body_size if large content triggers 413"],"exampleFix":"// before\nif (!res.ok) throw new Error(res.statusText || String(res.status));\n\n// after\nif (!res.ok) {\n  const t = await res.text().catch(() => '');\n  throw new Error(t || res.statusText || `HTTP ${res.status}`);\n}","handlingStrategy":"fallback","validationCode":"if (!docs.has(docId)) return false; // undo target already gone","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`${API_BASE}/api/document/${docId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ content: prev }) });\n  if (!res.ok) {\n    const t = await res.text().catch(() => '');\n    throw new Error(t || res.statusText || `HTTP ${res.status}`);\n  }\n  _setPdfSaveStatus('saved');\n  _renderPdfPane();\n  return true;\n} catch (e) {\n  _setPdfSaveStatus('error', e.message || 'Undo failed');\n  return true; // keep local content rolled back even if persist failed\n}","preventionTips":["Include the response body — statusText is often empty on modern proxies","Keep the local rollback (already done) so the editor state stays consistent on save failure","Handle 404/409 by offering to reload the doc rather than retrying the same PUT"],"tags":["fetch","http-error","save-conflict","document","undo"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}