{"record":{"id":"d2b5687d163c3feb","repo":"odysseus-dev/odysseus","slug":"await-pdfresponseerrormessage-res","errorCode":null,"errorMessage":"await _pdfResponseErrorMessage(res)","messagePattern":"await _pdfResponseErrorMessage\\(res\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/document.js","lineNumber":1161,"sourceCode":"      if (typeof data?.detail === 'string') return data.detail;\n      if (data?.detail) return JSON.stringify(data.detail);\n    } catch (_) {}\n    return text || res.statusText || `HTTP ${res.status}`;\n  }\n\n  async function _renderPdfPane() {\n    const pane = document.getElementById('doc-pdf-view');\n    if (!pane || !activeDocId) return;\n    _wirePdfPaneProximity(pane);\n    const docId = activeDocId;\n    // Keep the save pill across re-renders by detaching/re-attaching it\n    const savedPill = document.getElementById('doc-pdf-save-pill');\n    pane.innerHTML = '<div style=\"color:#bbb;font-size:13px;text-align:center;padding:40px;\">Loading PDF…</div>';\n    if (savedPill) pane.appendChild(savedPill);\n    let data;\n    try {\n      const res = await fetch(`${API_BASE}/api/document/${docId}/render-pages`);\n      if (!res.ok) throw new Error(await _pdfResponseErrorMessage(res));\n      data = await res.json();\n    } catch (e) {\n      pane.innerHTML = `<div style=\"color:#fbb;padding:40px;text-align:center;\">Failed to load PDF view: ${_escHtml(e.message || String(e))}</div>`;\n      if (savedPill) pane.appendChild(savedPill);\n      return;\n    }\n    if (docId !== activeDocId) return;\n\n    pane.innerHTML = '';\n    if (savedPill) pane.appendChild(savedPill);\n    const fieldRefs = [];\n    // Reset annotation refs for this doc before the page loop — we rebuild them\n    // page by page from the live markdown.\n    const annotationRefs = [];\n    _pdfPaneAnnotationsByDoc.set(docId, annotationRefs);\n    const liveMd = (docs.get(docId) && docs.get(docId).content) || '';\n    const allAnnotations = _parseAnnotations(liveMd);\n    // Recover the last-used line spacing from existing text annotations so the","sourceCodeStart":1143,"sourceCodeEnd":1179,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/document.js#L1143-L1179","documentation":"Error thrown while loading the PDF page view: GET /api/document/{docId}/render-pages answered non-OK, and _pdfResponseErrorMessage(res) formats the body/status into the message rendered inside the pane ('Failed to load PDF view: ...'). This is the primary load path for the PDF viewer.","triggerScenarios":"GET render-pages returns 404 (unknown doc), 422 (doc has no PDF), 500 (page rasterization crash — ghostworker/poppler missing, corrupt PDF, out-of-memory on huge files), 502 behind a proxy during long rendering.","commonSituations":"Backend PDF rendering dependency not installed in the deployment; very large PDFs timing out or exhausting memory; PDF replaced with a corrupt file; docId stale after switching sessions.","solutions":["Read the message shown in the pane — it comes from _pdfResponseErrorMessage and includes the backend detail","Verify the PDF renders in an external viewer (rules out corruption)","Install/verify the server-side render dependencies named in the backend logs","For giant PDFs, raise backend render timeouts or split the document"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"const doc = docs.get(docId);\nif (!doc || !doc.hasPdf) { pane.innerHTML = '<div ...>This document has no PDF view.</div>'; return; }","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`${API_BASE}/api/document/${docId}/render-pages`);\n  if (!res.ok) throw new Error(await _pdfResponseErrorMessage(res));\n  const data = await res.json();\n  if (docId !== activeDocId) return; // stale render\n  // ... build pages\n} catch (e) {\n  pane.innerHTML = `<div ...>Failed to load PDF view: ${_escHtml(e.message || String(e))}</div>`;\n  if (savedPill) pane.appendChild(savedPill);\n}","preventionTips":["Keep the docId-staleness check after every await (already present) to avoid clobbering a newer doc","Escape the error message before injecting into innerHTML (already done via _escHtml)","Offer a retry link in the failure pane for transient 5xx"],"tags":["fetch","http-error","pdf-render","document"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}