{"record":{"id":"7260a1b9968ceaf0","repo":"different-ai/openwork","slug":"xlsx-workbook-contained-no-sheets","errorCode":null,"errorMessage":"XLSX workbook contained no sheets.","messagePattern":"XLSX workbook contained no sheets\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/server/src/opencode-plugins/openwork-office-attachments.ts","lineNumber":637,"sourceCode":"      ...(displayValue !== undefined ? { displayedValue: displayValue } : {}),\n    });\n  }\n  return { dimension, mergedRanges, cells, omittedCells };\n}\n\nfunction quoted(value: string): string {\n  const encoded = JSON.stringify(value.length > 500 ? `${value.slice(0, 500)}…` : value);\n  return typeof encoded === \"string\" ? encoded : \"\\\"\\\"\";\n}\n\nfunction extractXlsxText(bytes: Buffer): string {\n  const entries = zipEntryMap(listZipEntries(bytes));\n  const workbookXml = readZipTextEntry(bytes, entries, \"xl/workbook.xml\");\n  if (!workbookXml) throw new Error(\"XLSX workbook.xml was not found.\");\n  const sharedStrings = parseSharedStrings(readZipTextEntry(bytes, entries, \"xl/sharedStrings.xml\"));\n  const numberFormats = parseXlsxNumberFormats(readZipTextEntry(bytes, entries, \"xl/styles.xml\"));\n  const sheets = parseWorkbookSheets(workbookXml, readZipTextEntry(bytes, entries, \"xl/_rels/workbook.xml.rels\"));\n  if (sheets.length === 0) throw new Error(\"XLSX workbook contained no sheets.\");\n\n  const lines = [\n    \"xlsx_workbook:\",\n    `  sheet_count: ${sheets.length}`,\n    `  shared_string_count: ${sharedStrings.length}`,\n    `  style_count: ${numberFormats.length}`,\n    \"  sheets:\",\n  ];\n  let remainingCells = MAX_XLSX_CELLS;\n  for (const sheet of sheets.slice(0, MAX_XLSX_SHEETS)) {\n    lines.push(`  - name: ${quoted(sheet.name)}`);\n    lines.push(`    sheet_id: ${quoted(sheet.sheetId)}`);\n    if (sheet.relationshipId) lines.push(`    relationship_id: ${quoted(sheet.relationshipId)}`);\n    lines.push(`    path: ${quoted(sheet.path)}`);\n    const safeSheetPath = sheet.path.startsWith(\"xl/worksheets/\") && sheet.path.endsWith(\".xml\") ? sheet.path : \"\";\n    const sheetXml = safeSheetPath ? readZipTextEntry(bytes, entries, safeSheetPath) : null;\n    if (!sheetXml) {\n      lines.push(\"    error: worksheet XML was not found or was outside xl/worksheets\");","sourceCodeStart":619,"sourceCodeEnd":655,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/opencode-plugins/openwork-office-attachments.ts#L619-L655","documentation":"Error thrown when an XLSX attachment contains a workbook.xml but it declares no sheet entries. This happens with edge-case or corrupt workbooks (e.g., all sheets deleted before saving, or malformed output from a third-party generator). The parser cannot extract any tabular data without at least one sheet. Fix by opening the file in a spreadsheet app, ensuring at least one sheet with data exists, and saving/re-uploading it.","triggerScenarios":"extractOfficeText(\"xlsx\", bytes) on a workbook.xml containing no <sheet> elements (or names the parser could not match) — damaged workbooks, programmatically generated files that omit sheets, or files stripped by sanitizers.","commonSituations":"Scripts generating xlsx with malformed workbook.xml; sanitizer/redaction pipelines that stripped sheet elements; corrupted files where relationship parsing dropped all sheets.","solutions":["Open the workbook in Excel, confirm it has sheets, and re-save it.","If generated programmatically, fix the generator to emit valid <sheet> entries in workbook.xml.","Check any XML-sanitizing step isn't stripping sheet elements.","Re-export the file from the originating tool."],"exampleFix":"// before: workbook.xml with no sheets\n<workbook><bookViews>...</bookViews></workbook>\n// after\n<workbook><sheets><sheet name=\"Sheet1\" sheetId=\"1\" r:id=\"rId1\"/></sheets></workbook>","handlingStrategy":"validation","validationCode":"function workbookHasSheets(workbookXml: string): boolean {\n  return /<sheet[\\s>]/i.test(workbookXml);\n}","typeGuard":"function hasExtractableSheets(sheets: unknown[]): boolean {\n  return Array.isArray(sheets) && sheets.length > 0;\n}","tryCatchPattern":"try {\n  const text = extractXlsxText(bytes);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"no sheets\")) {\n    throw new ApiError(400, \"invalid_xlsx\", \"Workbook has no sheets; re-save the file from Excel.\");\n  }\n  throw err;\n}","preventionTips":["Fix programmatic xlsx generators to emit <sheet> entries in workbook.xml.","Audit any XML-sanitizing/redaction step for over-stripping sheet elements.","Verify generated workbooks open correctly in Excel before serving.","Add a smoke test that extracts text from a minimal valid workbook."],"tags":["xlsx","office","xml","malformed-file"],"backgroundTag":"missing-required-archive-entry","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}