odysseus-dev/odysseus · error · Error
err || res.statusText
Error message
err || res.statusText
What it means
Error thrown when the export-preview POST /api/document/{id}/export-pdf/preview answers non-OK while building the field-review overlay. The raw body text (or statusText) becomes the message. The overlay is already on screen, so the error surfaces inside/around it.
Source
Thrown at static/js/document.js:708
<span id="pdf-export-status" style="font-size:0.75rem;opacity:0.7;margin-right:auto;"></span>
<button id="pdf-export-cancel" class="confirm-btn confirm-btn-secondary">Cancel</button>
<button id="pdf-export-download" class="confirm-btn confirm-btn-primary" disabled>Download PDF</button>
</div>
</div>
`;
document.body.appendChild(overlay);
const close = () => overlay.remove();
overlay.addEventListener('click', (e) => { if (e.target === overlay) close(); });
overlay.querySelector('#pdf-export-close').addEventListener('click', close);
overlay.querySelector('#pdf-export-cancel').addEventListener('click', close);
let fields = [];
try {
const res = await fetch(`${API_BASE}/api/document/${activeDocId}/export-pdf/preview`, { method: 'POST' });
if (!res.ok) {
const err = await res.text();
throw new Error(err || res.statusText);
}
const data = await res.json();
fields = data.fields || [];
const filledNow = data.filled || 0;
const total = data.total || fields.length;
overlay.querySelector('#pdf-export-summary').textContent =
`${filledNow} of ${total} fields filled. Review and adjust below before downloading.`;
const body = overlay.querySelector('#pdf-export-body');
body.innerHTML = '';
// Group by page
const byPage = new Map();
for (const f of fields) {
const p = f.page || 1;
if (!byPage.has(p)) byPage.set(p, []);
byPage.get(p).push(f);View on GitHub (pinned to f9235ebbf1)
Solutions
- Read the message body text — it is the backend's literal response
- Ensure the doc was imported from a PDF that contains form fields
- Retry after reloading the document list to refresh activeDocId
- Check server logs around the preview call for the extraction exception
Defensive patterns
Strategy: try-catch
Validate before calling
if (!activeDocId || !docs.get(activeDocId)) { close(); uiModule?.showError?.('Document no longer available'); return; } Try / catch
try {
const res = await fetch(`${API_BASE}/api/document/${activeDocId}/export-pdf/preview`, { method: 'POST' });
if (!res.ok) {
const err = await res.text().catch(() => '');
let msg = err;
try { msg = JSON.parse(err).detail || err; } catch {}
throw new Error(msg || res.statusText || `HTTP ${res.status}`);
}
const data = await res.json();
fields = data.fields || [];
} catch (e) {
overlay.querySelector('#pdf-export-summary').textContent = 'Preview failed: ' + e.message;
} Prevention
- Give the overlay an inline error region so failures don't strand a blank modal
- Close the overlay on 404/422 — those are unrecoverable for this doc
- Parse detail from JSON bodies before falling back to raw text
When it happens
Trigger: POST export-pdf/preview returns 404 (docId unknown), 422 (no PDF backing the doc), 500 (field extraction crash — PDF has no AcroForm, damaged xref), or HTML from an intermediary.
Common situations: Same as export: markdown-origin docs have no previewable form fields; encrypted or non-form PDFs break field extraction; backend PDF library version change altering extraction behavior; stale docId.
Related errors
- t || r.statusText
- res.statusText || String(res.status)
- await _pdfResponseErrorMessage(res)
- t || res.statusText
- t || r2.statusText
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/bcdf992e54251630.
Report an issue: GitHub.