{"record":{"id":"de16518fb276640a","repo":"odysseus-dev/odysseus","slug":"server-error","errorCode":null,"errorMessage":"Server error","messagePattern":"Server error","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"static/js/documentLibrary.js","lineNumber":1546,"sourceCode":"          continue;\n        }\n\n        if (isSpreadsheet) {\n          // Multi-sheet: create one document per sheet\n          await ensureXLSX();\n          const buf = await file.arrayBuffer();\n          const wb = window.XLSX.read(buf, { type: 'array' });\n          for (const sheetName of wb.SheetNames) {\n            const csv = window.XLSX.utils.sheet_to_csv(wb.Sheets[sheetName]);\n            if (!csv.trim()) continue;\n            const sheetTitle = wb.SheetNames.length > 1\n              ? `${baseTitle} - ${sheetName}` : baseTitle;\n            const res = await fetch(`${API_BASE}/api/document`, {\n              method: 'POST',\n              headers: { 'Content-Type': 'application/json' },\n              body: JSON.stringify({ title: sheetTitle, language: 'csv', content: csv }),\n            });\n            if (!res.ok) throw new Error('Server error');\n          }\n          imported++;\n        } else {\n          const content = await readFileContent(file);\n          const res = await fetch(`${API_BASE}/api/document`, {\n            method: 'POST',\n            headers: { 'Content-Type': 'application/json' },\n            body: JSON.stringify({ title: baseTitle, language, content }),\n          });\n          if (!res.ok) throw new Error('Server error');\n          imported++;\n        }\n      } catch (e) {\n        console.error('Failed to import file:', file.name, e);\n        if (!_firstErr) _firstErr = (e && e.message) || String(e);\n        failed++;\n      }\n    }","sourceCodeStart":1528,"sourceCodeEnd":1564,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/documentLibrary.js#L1528-L1564","documentation":"Thrown in documentLibrary.js's batch importer when creating a CSV document per spreadsheet sheet via POST /api/document returns non-2xx. The generic 'Server error' discards status and body; because this is inside a per-file loop, the failure aborts remaining sheets of that workbook and increments the failed counter shown in the summary.","triggerScenarios":"Sheet-to-CSV conversion succeeded but the create call rejects: content too large (413 — big sheets make huge JSON), schema validation on {title, language:'csv', content} (422), missing credentials note — these creates omit credentials: 'same-origin' unlike elsewhere — or genuine 500s.","commonSituations":"Importing multi-MB xlsx workbooks whose CSV expansion exceeds request limits; auth-requiring deployments where the omitted credentials cause 401; title with characters a strict backend rejects.","solutions":["Reproduce with a single-sheet small xlsx to separate size/auth causes.","Add credentials: 'same-origin' to these POST /api/document calls to match the rest of the app.","Raise the JSON body limit if large sheets are expected.","Include status/detail in the message instead of 'Server error'."],"exampleFix":"// before\nconst res = await fetch(`${API_BASE}/api/document`, {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({ title: sheetTitle, language: 'csv', content: csv }),\n});\nif (!res.ok) throw new Error('Server error');\n\n// after\nconst res = await fetch(`${API_BASE}/api/document`, {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  credentials: 'same-origin',\n  body: JSON.stringify({ title: sheetTitle, language: 'csv', content: csv }),\n});\nif (!res.ok) {\n  let detail = '';\n  try { const j = await res.json(); detail = j?.detail || j?.error || ''; } catch (_) {}\n  throw new Error(`Sheet import failed (${sheetTitle}): HTTP ${res.status}${detail ? ` — ${detail}` : ''}`);\n}","handlingStrategy":"validation","validationCode":"if (!csv.trim()) continue; // skip empty sheets before hitting the API\nif (csv.length > CSV_MAX_CHARS) { csv = csv.slice(0, CSV_MAX_CHARS); }","typeGuard":null,"tryCatchPattern":"const res = await fetch(`${API_BASE}/api/document`, {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  credentials: 'same-origin',\n  body: JSON.stringify({ title: sheetTitle, language: 'csv', content: csv }),\n});\nif (!res.ok) {\n  let detail = '';\n  try { const j = await res.json(); detail = j?.detail || ''; } catch (_) {}\n  throw new Error(`Sheet '${sheetTitle}' import failed: HTTP ${res.status}${detail ? ' — ' + detail : ''}`);\n}","preventionTips":["Send credentials: 'same-origin' on these creates — the library importer currently omits it.","Cap sheet CSV length client-side to stay under JSON body limits.","Name the failing sheet in the error; a workbook can have dozens and 'Server error' is unattributable."],"tags":["http","spreadsheet-import","document-create","credentials","poor-error-message"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}