FTS code analyzer: default max_token_length=40 silently drops long identifiers, so a class can't be found by its own name
Maintainers usually reply within 3 days
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 42/100
Research direction
Start with apply_code_defaults in src/lance/rust/lance-index/src/scalar/inverted/tokenizer.rs and the max_token_length handling around the cited lines. Run $S/hunt/tokenization/r3.py to reproduce the dropped identifier, then review src/lance/docs/src/guide/tokenizer.md and the create_scalar_index docstring. Done means the team has chosen a code-profile default, implemented it for new indexes, and documented the resulting behavior.
Written by the indexing model from the issue text.
Description
Bug bash: Needs team input — design question
Bug bash priority: Medium · critical-fix: no
From the FTS for Code bug bash (2026-10-01), findings: tokenization-3.md. Repros ran against released artifacts (pylance 12.0.0 / 13.0.0b18, lancedb 0.39.0 / 0.40.0b12, @lancedb/lancedb 0.40.0-beta.12) unless stated. $S is the bug bash scratch dir.
Decision needed: the default token length limit for the code profile.
Options:
- Raise or remove the limit for the code analyzer.
- Keep 40 but, with splitting on, keep the subwords and drop only the original (today the original is already dropped).
- Keep 40 and document it prominently.
Recommendation: 1 (for example 128), since identifiers over 40 bytes are common: about 9k Rust function names in our own repos.
- Category: feature gap (default choice) / docs gap
- Environment: pylance local, Python 3.12, Linux aarch64
- Artifacts: pylance 13.0.0b18 and 12.0.0 (identical output)
- Target tracker: GitHub
lance-format/lance
Repro
$S/hunt/tokenization/r3.py:
import lance, pyarrow as pa, tempfile
print("pylance", lance.__version__)
name = "AbstractSingletonProxyFactoryBeanTransactionInterceptorConfig" # 61 bytes
print(lance.tokenize(f"class {name} {{}}", analyzer="code"))
ds = lance.write_dataset(pa.table({"id": [0], "code": [f"class {name} {{}}"]}), tempfile.mkdtemp())
ds.create_scalar_index("code", "INVERTED", analyzer="code")
for q in [name, "class"]:
print(repr(q), "->", ds.to_table(full_text_query=q, columns=["id", "_score"])["id"].to_pylist())
Output:
pylance 13.0.0-beta.18
[FtsToken(text="class", position=0)]
'AbstractSingletonProxyFactoryBeanTransactionInterceptorConfig' -> []
'class' -> [0]
Expected behavior
The code profile keeps identifiers of realistic length by default: a larger limit, or no limit. At minimum, the code-analyzer docs warn that names over 40 bytes are not indexed unless max_token_length is raised.
Evidence: the create_scalar_index docstring documents max_token_length default 40 only as a text-profile option (src/lance/python/python/lance/dataset.py:3841-3843). The code-analyzer docs (src/lance/docs/src/guide/tokenizer.md:15-47) do not mention it. Long descriptive names are idiomatic for Java/C#/Rust tests.
Suspected root cause
apply_code_defaults (src/lance/rust/lance-index/src/scalar/inverted/tokenizer.rs:679-689) resets stem/stop words/folding but leaves max_token_length at the text default Some(40) (:641). RemoveLongFilter runs right after the word-delimiter stage (tokenizer.rs:1082-1083). The 40-byte limit was tuned for natural-language junk tokens (base64, hashes), not for identifiers.
Fix direction
Give the code profile its own max_token_length default (for example 128 or 255) in apply_code_defaults and document it. Needs a decision, because it changes the default for new indexes (existing ones persist their value).
- Dominant language
- Rust
- Stars
- 7.2k
- Forks
- 900
- Avg merge
- 4d 22h
- Merged PRs (30d)
- 366
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- Ships a Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from lance-format/lance
-
documentation
Difficulty 1/5 Under an hour Newbie friendliness 78/100
lance-format/lance#10225 ·
Maintainers usually reply within 3 days
-
feature performance
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
lance-format/lance#10137 ·
Maintainers usually reply within 3 days
-
After initialize_mem_wal, every FTS query logs "ERROR Index __lance_mem_wal has no fields"Possibly taken @lance-gatefixer claimed this 23 days ago. Openbug
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
lance-format/lance#9655 ·
Maintainers usually reply within 3 days
-
Upgrade DataFusion for the unparser stack-overflow fixMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
lance-format/lance#8225 ·
Maintainers usually reply within 3 days
-
enhancement
Difficulty 1/5 Under an hour Newbie friendliness 84/100
lance-format/lance#6425 · 2 comments ·
Maintainers usually reply within 3 days
All issues in lance-format/lance
Similar issues
-
bug easy good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
lacs-project/sysknife#659 ·
Maintainers usually reply within 2 days
-
E_FIT_INPUT_MISSING (mixture overrides): the message says ferx-r bundles lack mixture_overridesOpenP3
Difficulty 1/5 Under an hour Newbie friendliness 83/100
Maintainers usually reply within 1 day
-
documentation
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
registrystack/registry-stack#2431 ·
Maintainers usually reply within 1 day
-
contribution
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
farion1231/cc-switch#8863 · 1 comment ·
Maintainers usually reply within 1 day