google-gemini / google-gemini/gemini-cli
web_fetch drops the rows and columns of every table on a page
- Dominant language
- TypeScript
- Stars
- 107k
- Forks
- 14.6k
- Avg merge
- 2d 3h
- Merged PRs (30d)
- 45
Description
### What happened?
`web_fetch` loses every table on a fetched page. `html-to-text` renders a `` as a plain block unless it is given a `table` selector, and a block joins its children with **nothing at all**. `packages/core/src/tools/web-fetch.ts` never passes one, at either of its two conversion sites (the fallback path at ~line 336 and the experimental path at ~line 710).
Measured against the pinned library (`html-to-text` 9.0.5) with the exact options the tool passes:
```js
convert(html, {
wordwrap: false,
selectors: [
{ selector: 'a', options: { ignoreHref: true } },
{ selector: 'img', format: 'skip' },
],
});
```
**Minified source — what most sites ship:**
```
PlanPriceSeats
Starter9 EUR3
Pro29 EUR10
-> PlanPriceSeatsStarter9 EUR3Pro29 EUR10
```
Not one boundary between two values survives: `9 EUR`, `3` and `Pro` become the single token `9 EUR3Pro`.
**Indented source — a hand-written page:**
```
-> Plan Price Seats Starter 9 EUR 3 Pro 29 EUR 10
```
The words are at least separated here, but the whole table is one line and nothing records which row or column a value came from.
### What did you expect to happen?
The cells to stay in their row and column, so the model can answer a question about the table. `html-to-text` already ships the formatter for it — `{ selector: 'table', format: 'dataTable' }` — and with it the same input converts to:
```
PLAN PRICE SEATS
Starter 9 EUR 3
Pro 29 EUR 10
```
### Client information
Client Information
Reproduced against the repository source rather than a running CLI, so there is no `/about` dump to paste. The coordinates that matter:
```console
repository google-gemini/gemini-cli @ 6a466a7 (main)
package 0.62.0-nightly.20260915
dependency html-to-text 9.0.5 (pinned in packages/core/package.json)
node v24.2.0
platform macOS (darwin)
```
### Login information
Not applicable — the failure is in the HTML-to-text conversion and reproduces in a unit-level call, with no model or auth involved.
### Anything else we need to know?
Pricing tables, API parameter tables, comparison matrices, release-note tables and spec sheets are among the most common reasons to fetch a URL, and they are exactly the content a model cannot reconstruct once the grid is gone — it has no way to tell whether `9 EUR` belonged to Starter or to Pro.
I have the fix and tests ready and will open a PR referencing this issue.
Contributor guide
Research direction
Read packages/core/src/tools/web-fetch.ts at the fallback conversion around line 336 and the experimental conversion around line 710, then compare their html-to-text options with the reported dataTable formatter. Ensure both paths preserve table rows and columns, and run or add unit-level tests covering the shown table cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- Half a day
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100