{"record":{"id":"6ee86a87749a093a","repo":"odysseus-dev/odysseus","slug":"t-r-statustext","errorCode":null,"errorMessage":"t || r.statusText","messagePattern":"t \\|\\| r\\.statusText","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/document.js","lineNumber":624,"sourceCode":"    const ae = document.activeElement;\n    const el = (ae && (ae.tagName === 'INPUT' || ae.tagName === 'TEXTAREA')) ? ae : ta;\n    if (!el) return;\n    try {\n      el.setAttribute('readonly', 'readonly');\n      el.blur();\n      setTimeout(() => { try { el.removeAttribute('readonly'); } catch (_) {} }, 120);\n    } catch (_) { try { el.blur(); } catch (_) {} }\n  }\n\n  async function _downloadFilledPdf() {\n    if (!activeDocId) return;\n    _dismissDocKb();   // export shouldn't leave the keyboard up\n    await _saveActiveDocBeforeExport();\n    try {\n      const r = await fetch(`${API_BASE}/api/document/${activeDocId}/export-pdf`);\n      if (!r.ok) {\n        const t = await r.text();\n        throw new Error(t || r.statusText);\n      }\n      const blob = await r.blob();\n      const url = URL.createObjectURL(blob);\n      const a = document.createElement('a');\n      a.href = url;\n      const cd = r.headers.get('Content-Disposition') || '';\n      const m = cd.match(/filename\\*?=(?:UTF-8'')?\"?([^\"';]+)/i);\n      const _slug = (s) => (s || 'form').replace(/\\.pdf$/i, '').replace(/\\s+/g, '_').replace(/[^A-Za-z0-9._-]/g, '').replace(/_+/g, '_').replace(/^_|_$/g, '') || 'form';\n      a.download = (m && decodeURIComponent(m[1])) || (_slug(docs.get(activeDocId)?.title) + '_annotated.pdf');\n      document.body.appendChild(a);\n      a.click();\n      a.remove();\n      setTimeout(() => URL.revokeObjectURL(url), 1000);\n    } catch (e) {\n      if (uiModule) uiModule.showError('Export failed: ' + e.message);\n      else alert('Export failed: ' + e.message);\n    }\n  }","sourceCodeStart":606,"sourceCodeEnd":642,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/document.js#L606-L642","documentation":"Error thrown when the direct PDF export GET /api/document/{id}/export-pdf returns non-OK. The response body text is used verbatim as the message (fallback: statusText). Because the endpoint returns a PDF blob on success, an error body is typically plain text or JSON from the backend (e.g. 'document has no PDF backing').","triggerScenarios":"GET export-pdf returns 404 (unknown docId), 409/400 (document is markdown-only with no PDF to fill), 500 (pdf processing crash — malformed PDF, missing fillable fields), or a proxy HTML error page that then shows as raw HTML in the toast.","commonSituations":"Doc was created from text/markdown so no source PDF exists; the uploaded PDF is encrypted/corrupt; backend pdf library dependency missing; docId stale after a reload/deletion.","solutions":["Read the thrown text — it is the endpoint's literal error body","Confirm the document actually has a PDF backing (it must have been imported from a PDF)","If the PDF is fillable-form-based, verify it opens in a viewer and is not password-protected","Check backend logs for the PDF-generation exception"],"exampleFix":"// before\nconst t = await r.text();\nthrow new Error(t || r.statusText);\n\n// after\nconst t = await r.text().catch(() => '');\nlet msg = t;\ntry { msg = JSON.parse(t).detail || t; } catch {}\nthrow new Error(msg || r.statusText || `HTTP ${r.status}`);","handlingStrategy":"try-catch","validationCode":"const doc = docs.get(activeDocId);\nif (!doc || !doc.hasPdf) { uiModule?.showToast?.('This document has no PDF to export'); return; }","typeGuard":null,"tryCatchPattern":"try {\n  const r = await fetch(`${API_BASE}/api/document/${activeDocId}/export-pdf`);\n  if (!r.ok) {\n    const t = await r.text().catch(() => '');\n    let msg = t;\n    try { msg = JSON.parse(t).detail || t; } catch {}\n    throw new Error(msg || r.statusText || `HTTP ${r.status}`);\n  }\n  const blob = await r.blob();\n  // ... trigger download\n} catch (e) {\n  uiModule?.showError?.('PDF export failed: ' + e.message);\n}","preventionTips":["Parse JSON detail out of the error body — raw text bodies make ugly toasts","Verify the document is PDF-backed before showing the export action","Always pass a text() fallback so empty error bodies still yield a status"],"tags":["fetch","http-error","pdf-export","document"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}