#16024·LibreChat

Tables in an uploaded .docx reach the model as a flat list of cells

Author: L4XBCreated Sep 16, 2026Updated Sep 16, 2026

What happens

Every table in an uploaded .docx reaches the model as a flat list of cell values. wordDocToText in packages/api/src/files/documents/crud.ts calls mammoth.extractRawText, and mammoth's raw-text writer has no table support: it emits each cell as its own paragraph and drops the row and column structure entirely.

Steps to reproduce

Build a three-column table in a .docx and run it through the same call the parser makes. Against eaa91b3:

javascript
const mammoth = require('mammoth');
const raw = await mammoth.extractRawText({ buffer: fs.readFileSync('table.docx') });

Document:

Region Product Units
EU Cable 12
US Hub 7

What extractRawText returns, verbatim:

Intro paragraph.

Region

Product

Units

EU

Cable

12

US

Hub

7

Closing paragraph.

12 is no longer connected to EU or to Units, and US sits between the two rows as if it were another value in the same list. Nothing in the text says a table was ever there.

Expected behavior

The cells stay associated with their row and their column, the way excelSheetToText already keeps a spreadsheet's rows together through utils.sheet_to_csv. Something like:

Region, Product, Units
EU, Cable, 12
US, Hub, 7

Why it matters

A table is usually the densest part of a Word document — invoice line items, a spec sheet, a comparison, a schedule. Asking a model "what does the EU pay per cable" over the text above cannot be answered correctly except by luck, because the association it needs was destroyed before the model saw it.

The information is not lost upstream: mammoth.convertToHtml on the same file returns the full structure.

xml
<p>Intro paragraph.</p><table><tr><td><p>Region</p></td><td><p>Product</p></td><td><p>Units</p></td></tr>
<tr><td><p>EU</p></td><td><p>Cable</p></td><td><p>12</p></td></tr></table><p>Closing paragraph.</p>

Two things I checked so they do not cost you time:

  • mammoth.convertToMarkdown does not help — its markdown writer flattens tables the same way (measured on mammoth 1.11.0, the pinned version).
  • so the fix means converting mammoth's HTML rather than its raw text, and that is an architecture call rather than a one-liner: packages/api has no HTML-to-text converter today, though jsdom and sanitize-html are already peer dependencies and html.ts owns the HTML side of this pipeline.

I have this reproduced with a regression test and I am happy to open a PR, but I did not want to pick the conversion approach for you. If you tell me which you would prefer — a small local renderer over mammoth's HTML, reusing something in html.ts, or a converter dependency — I will build it that way.

Environment

  • LibreChat source at eaa91b3 on main
  • mammoth 1.11.0, the version pinned in packages/api/package.json
  • Node.js 24.2.0, macOS
  • Reproduced against the source rather than a running instance; the failure is in the parser and shows up in a unit-level call.