Skip to content

fix(fts): use complete English stop-word list for ICU tokenizer#7621

Open
LuQQiu wants to merge 4 commits into
lance-format:mainfrom
LuQQiu:lu/debug_fts_stop
Open

fix(fts): use complete English stop-word list for ICU tokenizer#7621
LuQQiu wants to merge 4 commits into
lance-format:mainfrom
LuQQiu:lu/debug_fts_stop

Conversation

@LuQQiu

@LuQQiu LuQQiu commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

The ICU tokenizer's stop-word removal used an incomplete English stop-word list, letting the highest-frequency English pronouns/function words through the index. On large corpora this built pathologically large single-term posting lists and panicked the FTS index build with posting list memory size overflowed u32.

StopWordFilter::all() (the path used for base_tokenizer: icu / icu/split) sourced its English words from the local Tantivy-style stopwords::ENGLISH constant (~33 words):

a an and are as at be but by for if in into is it no not of on or such
that the their then there these they this to was will with

This omits extremely common words: you, my, your, we, she, what, can, about, us, them, him, our. Since these are among the highest-frequency tokens in English text, they survived stop-word removal. With with_position: true on a 100M+ row dataset, a single such term's in-memory posting list exceeded u32::MAX bytes (~4 GiB) and panicked the whole build.

Root cause

Every other language in all_stop_words() (Arabic, Chinese, Japanese, Korean, …) is sourced from the stop-words crate via stop_words::get(...), whose lists are complete. Only English used the local, truncated constant. The Chinese list (stop_words::get("zh"), ~841 words) was already complete — Chinese stop words like 了/是/的 were correctly removed; only English leaked.

Fix

One-line change in all_stop_words(): source English from stop_words::get("en") (~198 words) like the other languages. This list contains the missing pronouns/function words.

Tests

  • test_icu_common_english_stop_words_do_not_leak — asserts you/my/your/we are removed via the ICU all() path, for icu and icu/split, with stem both false and true (the leak is independent of stemming — it's purely the incomplete list).
  • test_icu_common_chinese_stop_words_do_not_leak — asserts common Chinese function words (我 在 有 了 是 的 和) are removed while content words (英语) survive.

All existing tokenizer tests continue to pass (20 passed, 0 failed).

Impact

Fixes FTS index builds that panicked on large English (and mixed EN+ZH) corpora, and reduces index size by correctly dropping the highest-frequency English stop words.

🤖 Generated with Claude Code

LuQQiu and others added 2 commits July 3, 2026 18:47
The ICU stop-word path (StopWordFilter::all()) sourced its English list
from the local Tantivy-style stopwords::ENGLISH constant (~33 words),
which omits extremely common pronouns and function words: you, my, your,
we, she, what, can, about, us, them, him, our.

Because these are the highest-frequency tokens in English text, they
survived stop-word removal and built pathologically large single-term
posting lists. On large corpora (100M+ rows) with positions enabled, one
such term's in-memory posting list exceeded u32::MAX bytes and panicked
the whole FTS index build with 'posting list memory size overflowed u32'.

Switch the English source to stop_words::get("en") (~198 words), matching
how the other CJK/misc languages in all_stop_words() are already sourced
from the stop-words crate. The leak is independent of stemming, so the
new tests cover both stem=false and stem=true for icu and icu/split.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds a regression test alongside the English one confirming common
Chinese function words/particles (我 在 有 了 是 的 和) are removed by the
ICU all() stop-word path while real content words (英语) survive. The
Chinese list is sourced from stop_words::get("zh") (complete), so this
already passed; the test locks it in.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added A-index Vector index, linalg, tokenizer bug Something isn't working labels Jul 4, 2026
LuQQiu and others added 2 commits July 3, 2026 18:54
…th too

The per-language StopWordFilter::new(English) path (used by non-ICU
tokenizers such as `simple`, the recommended tokenizer for monolingual
English) also sourced the truncated local stopwords::ENGLISH (~33 words),
so common pronouns (you/my/your/we/...) leaked there as well. Switch it to
stop_words::get("en") to match the ICU all() path fix, and extend the
regression test to cover base_tokenizer=simple.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-index Vector index, linalg, tokenizer bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant