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 the

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Read the message shown in the pane — it comes from _pdfResponseErrorMessage and includes the backend detail
  2. Verify the PDF renders in an external viewer (rules out corruption)
  3. Install/verify the server-side render dependencies named in the backend logs
  4. 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

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


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/d2b5687d163c3feb. Report an issue: GitHub.