{"record":{"id":"86fa84133a6db845","repo":"odysseus-dev/odysseus","slug":"failed","errorCode":null,"errorMessage":"Failed","messagePattern":"Failed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/document.js","lineNumber":5780,"sourceCode":"      }\n    });\n\n    // Diff toggle button — compare current content against previous version\n    const diffToggleBtn = document.getElementById('doc-diff-toggle-btn');\n    if (diffToggleBtn) diffToggleBtn.addEventListener('click', async () => {\n      if (_diffModeActive) {\n        exitDiffMode(true);\n        return;\n      }\n      if (!activeDocId) return;\n      const ta = document.getElementById('doc-editor-textarea');\n      if (!ta) return;\n      const current = ta.value;\n\n      // Fetch version history and compare against previous version\n      try {\n        const res = await fetch(`${API_BASE}/api/document/${activeDocId}/versions`);\n        if (!res.ok) throw new Error('Failed');\n        const versions = await res.json();\n        if (versions.length < 2) {\n          if (uiModule) uiModule.showToast('No previous version to compare');\n          return;\n        }\n        // versions are sorted desc — [0] is latest, [1] is previous\n        const prevContent = versions[1].content || '';\n        if (prevContent === current) {\n          if (uiModule) uiModule.showToast('No changes from previous version');\n          return;\n        }\n        enterDiffMode(prevContent, current);\n      } catch {\n        if (uiModule) uiModule.showError('Failed to load version history');\n      }\n    });\n\n    // Export PDF (form-backed markdown docs)","sourceCodeStart":5762,"sourceCodeEnd":5798,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/document.js#L5762-L5798","documentation":"Thrown in the diff/version-compare handler of static/js/document.js when GET /api/document/<id>/versions returns non-2xx. The unhelpful message 'Failed' replaces the status, so the console error (and the catch that follows) is the only diagnostic. It fires before any version comparison happens.","triggerScenarios":"Clicking the compare/diff action on a document that was deleted server-side (404), with an expired session (401), or while the backend is down (network TypeError would actually be thrown by fetch itself and bypass this line).","commonSituations":"Comparing versions of a doc whose autosave 404s were already being swallowed; local tab pointing at a document purged by server-side cleanup; API route missing after downgrade.","solutions":["Reproduce with the Network tab open and note the real status code for /api/document/<id>/versions.","If 404, reopen the document from the Library — the local tab references a deleted doc.","Improve the message to include res.status (and res.statusText) so future hits are self-describing.","Verify auth/session if 401/403."],"exampleFix":"// before\nif (!res.ok) throw new Error('Failed');\n\n// after\nif (!res.ok) throw new Error(`Failed to load versions: HTTP ${res.status}`);","handlingStrategy":"try-catch","validationCode":"if (!activeDocId) return;\nconst doc = docs.get(activeDocId);\nif (!doc) return; // no local doc to diff","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`${API_BASE}/api/document/${activeDocId}/versions`, { credentials: 'same-origin' });\n  if (!res.ok) throw new Error(`Failed to load versions: HTTP ${res.status}`);\n  const versions = await res.json();\n  if (!Array.isArray(versions)) throw new Error('Unexpected versions payload');\n  if (versions.length < 2) { if (uiModule) uiModule.showToast('No previous version to compare'); return; }\n} catch (e) {\n  if (uiModule) uiModule.showError('Could not load version history');\n}","preventionTips":["Include the status code in every thrown HTTP error — bare 'Failed' wastes a repro cycle.","Treat a 404 on versions like saveDocument treats it: the doc may be gone; offer to reopen from the Library.","Send credentials explicitly on all API fetches for consistency."],"tags":["http","versions","diff","poor-error-message"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}