{"record":{"id":"d133f7b612bdd9d2","repo":"different-ai/openwork","slug":"office-xml-text-entries-contained-no-extractable-t","errorCode":null,"errorMessage":"Office XML text entries contained no extractable text.","messagePattern":"Office XML text entries contained no extractable text\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/server/src/opencode-plugins/openwork-office-attachments.ts","lineNumber":695,"sourceCode":"  return lines.join(\"\\n\").slice(0, MAX_EXTRACTED_TEXT_CHARS);\n}\n\nfunction extractOfficeText(kind: OfficeKind, bytes: Buffer): string {\n  if (kind === \"xlsx\") return extractXlsxText(bytes);\n  const entries = listZipEntries(bytes).filter((entry) => relevantXmlEntry(kind, entry.name)).sort(compareEntryName);\n  if (entries.length === 0) throw new Error(\"No supported Office XML text entries were found.\");\n  const pieces: string[] = [];\n  let remaining = MAX_EXTRACTED_TEXT_CHARS;\n  for (const entry of entries) {\n    if (remaining <= 0) break;\n    const text = xmlText(readZipEntryData(bytes, entry).toString(\"utf8\"));\n    if (!text) continue;\n    const chunk = text.slice(0, remaining);\n    pieces.push(`[${entry.name}]\\n${chunk}`);\n    remaining -= chunk.length;\n  }\n  const combined = pieces.join(\"\\n\\n\").slice(0, MAX_EXTRACTED_TEXT_CHARS);\n  if (!combined) throw new Error(\"Office XML text entries contained no extractable text.\");\n  return combined;\n}\n\nfunction basePartIds(part: Record<string, unknown>): Record<string, unknown> {\n  const result: Record<string, unknown> = {};\n  for (const key of [\"id\", \"sessionID\", \"messageID\", \"sessionId\", \"messageId\"]) {\n    const value = part[key];\n    if (typeof value === \"string\" || typeof value === \"number\") result[key] = value;\n  }\n  return result;\n}\n\nfunction normalizedText(part: OfficeFilePart, materialized: MaterializedAttachment | null, extractedText: string, error?: string): string {\n  return [\n    \"OpenWork normalized an Office attachment before sending this request to the model.\",\n    `filename: ${safeFilename(part.filename, part.kind)}`,\n    `canonical_mime: ${part.mime}`,\n    `sha256: ${materialized?.sha256 ?? \"unavailable\"}`,","sourceCodeStart":677,"sourceCodeEnd":713,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/opencode-plugins/openwork-office-attachments.ts#L677-L713","documentation":"After collecting text from all relevant Office XML parts, if the combined extracted text is empty (every part yielded no text or the budget was exhausted before any chunk), extractOfficeText throws this error. It means the archive was structurally fine but had no extractable textual content.","triggerScenarios":"extractOfficeText on docx/pptx whose XML parts contain only whitespace/empty runs, only images/shapes without text, or where remaining char budget was already <= 0 (e.g., MAX_EXTRACTED_TEXT_CHARS configured to 0).","commonSituations":"Image-only documents (scanned pages); presentations with only pictures; documents whose text lives in unsupported parts; misconfigured MAX_EXTRACTED_TEXT_CHARS = 0.","solutions":["Verify the document actually contains text (open it and check).","Check MAX_EXTRACTED_TEXT_CHARS isn't 0 or negative in config.","For image-only documents, use OCR instead of XML extraction.","Ensure document text isn't stored only in embedded objects (e.g., embedded xlsx/charts) that the extractor skips."],"exampleFix":"// before\nconst MAX_EXTRACTED_TEXT_CHARS = Number(process.env.MAX_TEXT_CHARS ?? 0);\n// after\nconst MAX_EXTRACTED_TEXT_CHARS = Number(process.env.MAX_TEXT_CHARS ?? 200_000);","handlingStrategy":"try-catch","validationCode":"function configAllowsExtraction(): boolean {\n  return Number(process.env.MAX_TEXT_CHARS ?? 200_000) > 0;\n}","typeGuard":"function hasExtractableText(pieces: string[]): boolean {\n  return pieces.some((p) => p.trim().length > 0);\n}","tryCatchPattern":"try {\n  const text = extractOfficeText(kind, bytes);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"no extractable text\")) {\n    return \"\"; // treat as image-only/empty document rather than failing\n  }\n  throw err;\n}","preventionTips":["Ensure MAX_EXTRACTED_TEXT_CHARS is positive in configuration.","Handle image-only/scanned documents with OCR before XML extraction.","Test extraction against image-only fixtures to decide empty-vs-error semantics.","Check documents aren't text-only inside unsupported embedded objects."],"tags":["office","text-extraction","empty-content"],"backgroundTag":"empty-extraction-result","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}