From e2899e4dea2562aab159bc1db8ccd21a87fefcbc Mon Sep 17 00:00:00 2001 From: "lancedb-gatefixer[bot]" <313497061+lancedb-gatefixer[bot]@users.noreply.github.com> Date: Thu, 8 Oct 2026 19:45:09 -0700 Subject: [PATCH] fix(node): reject unsupported FTS languages without panicking (#4369) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Index.fts({ language: "english" })` and other unsupported language values abort the Node process because the native factory unwraps the error returned by `FtsIndexBuilder::language`. Convert that error into a catchable JavaScript `Error`, using the same message as `tokenize` and Python. Add regression coverage for `"Klingon"` and lowercase `"english"`, plus a valid English stemming and search case across Arrow 15–18. Validation: - Native and TypeScript builds: `pnpm build:debug --profile ci` and `pnpm tsc`. - Full-text and tokenization tests: `pnpm test __test__/table.test.ts --runInBand --testNamePattern 'full text|FTS|tokeniz'` — 69 passed. - Rust formatting and lint: `cargo fmt --all`; `cargo clippy --profile ci --target x86_64-unknown-linux-gnu -p lancedb-nodejs -- -D warnings`. - TypeScript formatting and lint: `pnpm exec biome format --write __test__/table.test.ts` and `pnpm lint`; `pnpm run docs` passed without generated changes. Fixes #4367 Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com> --- nodejs/__test__/table.test.ts | 22 ++++++++++++++++++++++ nodejs/src/index.rs | 7 ++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/nodejs/__test__/table.test.ts b/nodejs/__test__/table.test.ts index 5a27b852b..837d9b608 100644 --- a/nodejs/__test__/table.test.ts +++ b/nodejs/__test__/table.test.ts @@ -4050,6 +4050,28 @@ describe.each(arrowVersions)( ); }); + test.each(["Klingon", "english"])( + "rejects unsupported full text language %s with a catchable error", + (language) => { + expect(() => Index.fts({ language })).toThrow( + new Error( + `LanceDB does not support the requested language: '${language}'`, + ), + ); + }, + ); + + test("full text search with a supported language", async () => { + const db = await connect(tmpDir.name); + const table = await db.createTable("test", [{ text: "running" }]); + await table.createIndex("text", { + config: Index.fts({ language: "English", stem: true }), + }); + + const results = await table.search("run").toArray(); + expect(results.map((row) => row.text)).toEqual(["running"]); + }); + test("full text search without lowercase", async () => { const db = await connect(tmpDir.name); const data = [ diff --git a/nodejs/src/index.rs b/nodejs/src/index.rs index 762f74870..e5884aa4d 100644 --- a/nodejs/src/index.rs +++ b/nodejs/src/index.rs @@ -239,7 +239,12 @@ impl Index { opts = opts.base_tokenizer(base_tokenizer); } if let Some(language) = language { - opts = opts.language(&language).unwrap(); + opts = opts.language(&language).map_err(|_| { + napi::Error::from_reason(format!( + "LanceDB does not support the requested language: '{}'", + language + )) + })?; } if let Some(max_token_length) = max_token_length { opts = opts.max_token_length(Some(max_token_length as usize));