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

  1. Read the message body text — it is the backend's literal response
  2. Ensure the doc was imported from a PDF that contains form fields
  3. Retry after reloading the document list to refresh activeDocId
  4. 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

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


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