{"record":{"id":"6d5d89eb67da043b","repo":"different-ai/openwork","slug":"xlsx-workbook-xml-was-not-found","errorCode":null,"errorMessage":"XLSX workbook.xml was not found.","messagePattern":"XLSX workbook\\.xml was not found\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/server/src/opencode-plugins/openwork-office-attachments.ts","lineNumber":633,"sourceCode":"      ...(formulaBlock ? { formula: xmlText(formulaBlock.inner) } : {}),\n      ...(formulaBlock?.attributes.t ? { formulaType: formulaBlock.attributes.t } : {}),\n      ...(formulaBlock?.attributes.ref ? { formulaRef: formulaBlock.attributes.ref } : {}),\n      ...(rawValue !== undefined ? { rawValue } : {}),\n      ...(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)}`);","sourceCodeStart":615,"sourceCodeEnd":651,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/opencode-plugins/openwork-office-attachments.ts#L615-L651","documentation":"Error thrown while parsing an uploaded XLSX (Excel) attachment: the ZIP archive was opened but the required workbook.xml part is missing from it. This means the file is not a valid XLSX workbook — commonly it is a renamed CSV/XML file, an .xls (legacy binary) file renamed to .xlsx, a corrupted download, or an empty/partial file. Fix by re-exporting the file as a genuine .xlsx from Excel/LibreOffice and re-uploading.","triggerScenarios":"extractOfficeText(\"xlsx\", bytes) on a file whose zip lacks xl/workbook.xml — an empty or non-Office zip renamed to .xlsx, a badly re-zipped archive with a wrong root folder, or an encrypted workbook.","commonSituations":"Users renaming .zip/.xls to .xlsx; archives created without the xl/ folder prefix; password-protected workbooks stored encrypted; attachments corrupted so entries were dropped.","solutions":["Open the file in Excel/LibreOffice and re-save it as a proper .xlsx, then retry.","Verify the zip contains xl/workbook.xml at the root-relative path (unzip -l file.xlsx | grep workbook.xml).","Ensure the upload is a real xlsx, not a renamed xls/csv/zip.","Check the file isn't password-protected/encrypted.","Re-create the archive preserving the original folder structure (OOXML root must contain [Content_Types].xml, xl/, etc.)."],"exampleFix":"// before: trusting the extension\nif (file.name.endsWith(\".xlsx\")) return extractXlsxText(bytes);\n// after: verify structure first\nif (file.name.endsWith(\".xlsx\")) {\n  if (!zipHasEntry(bytes, \"xl/workbook.xml\")) throw new ApiError(400, \"invalid_xlsx\", \"Not a valid XLSX workbook\");\n  return extractXlsxText(bytes);\n}","handlingStrategy":"validation","validationCode":"import { readFile } from \"node:fs/promises\";\nasync function looksLikeXlsx(path: string): Promise<boolean> {\n  const buf = await readFile(path);\n  return buf.subarray(0, 2).toString(\"latin1\") === \"PK\" && buf.includes(Buffer.from(\"xl/workbook.xml\"));\n}","typeGuard":"function hasWorkbookEntry(bytes: Buffer): boolean {\n  return bytes.includes(Buffer.from(\"xl/workbook.xml\"));\n}","tryCatchPattern":"try {\n  const text = extractXlsxText(bytes);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"workbook.xml was not found\")) {\n    throw new ApiError(400, \"invalid_xlsx\", \"File is not a valid XLSX workbook; please re-save it from Excel.\");\n  }\n  throw err;\n}","preventionTips":["Validate file structure, not just the .xlsx extension, before extraction.","Reject password-protected/encrypted workbooks up front with a clear message.","Re-save files from Excel/LibreOffice if they came from nonstandard generators.","Use unzip -l to confirm required OOXML parts during debugging."],"tags":["xlsx","office","zip","missing-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"}