odysseus-dev/odysseus · error · Error
await _pdfResponseErrorMessage(res)
Error message
await _pdfResponseErrorMessage(res)
What it means
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.
Source
Thrown at static/js/document.js:1161
if (typeof data?.detail === 'string') return data.detail;
if (data?.detail) return JSON.stringify(data.detail);
} catch (_) {}
return text || res.statusText || `HTTP ${res.status}`;
}
async function _renderPdfPane() {
const pane = document.getElementById('doc-pdf-view');
if (!pane || !activeDocId) return;
_wirePdfPaneProximity(pane);
const docId = activeDocId;
// Keep the save pill across re-renders by detaching/re-attaching it
const savedPill = document.getElementById('doc-pdf-save-pill');
pane.innerHTML = '<div style="color:#bbb;font-size:13px;text-align:center;padding:40px;">Loading PDF…</div>';
if (savedPill) pane.appendChild(savedPill);
let data;
try {
const res = await fetch(`${API_BASE}/api/document/${docId}/render-pages`);
if (!res.ok) throw new Error(await _pdfResponseErrorMessage(res));
data = await res.json();
} catch (e) {
pane.innerHTML = `<div style="color:#fbb;padding:40px;text-align:center;">Failed to load PDF view: ${_escHtml(e.message || String(e))}</div>`;
if (savedPill) pane.appendChild(savedPill);
return;
}
if (docId !== activeDocId) return;
pane.innerHTML = '';
if (savedPill) pane.appendChild(savedPill);
const fieldRefs = [];
// Reset annotation refs for this doc before the page loop — we rebuild them
// page by page from the live markdown.
const annotationRefs = [];
_pdfPaneAnnotationsByDoc.set(docId, annotationRefs);
const liveMd = (docs.get(docId) && docs.get(docId).content) || '';
const allAnnotations = _parseAnnotations(liveMd);
// Recover the last-used line spacing from existing text annotations so theView on GitHub (pinned to f9235ebbf1)
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
Defensive patterns
Strategy: try-catch
Validate before calling
const doc = docs.get(docId);
if (!doc || !doc.hasPdf) { pane.innerHTML = '<div ...>This document has no PDF view.</div>'; return; } Try / catch
try {
const res = await fetch(`${API_BASE}/api/document/${docId}/render-pages`);
if (!res.ok) throw new Error(await _pdfResponseErrorMessage(res));
const data = await res.json();
if (docId !== activeDocId) return; // stale render
// ... build pages
} catch (e) {
pane.innerHTML = `<div ...>Failed to load PDF view: ${_escHtml(e.message || String(e))}</div>`;
if (savedPill) pane.appendChild(savedPill);
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- t || r.statusText
- err || res.statusText
- res.statusText || String(res.status)
- t || res.statusText
- t || r2.statusText
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/d2b5687d163c3feb.
Report an issue: GitHub.