Commit Graph
3169 Commits
Author SHA1 Message Date
Brendan Clement bbadf0dbea docs: qualify what deployments do with materialized views
The SDK now sends CREATE MATERIALIZED VIEW and REFRESH MATERIALIZED VIEW
to a db:// deployment as SQL, and refuses source_version on a remote
refresh. Current Sophon source accepts both statements, with CASCADE and
WITH (full = true), but only on deployments that enable materialized
views, and whether a refresh rebuilds the view or reconciles changes
depends on configuration. The pages said there is no CREATE MATERIALIZED
VIEW statement, that refreshes are incremental by default and that
CASCADE is not implemented.

The refresh, management and SQL reference pages now describe what the
SDK sends, say that materialized views are experimental and must be
enabled on a deployment, and leave refresh behaviour, CASCADE and the
job type to the deployment's version and configuration. The SQL and
management summaries list CREATE MATERIALIZED VIEW. No deployment was
exercised.
2026-10-06 20:45:28 -07:00
Brendan Clement 622e6078c1 docs: describe materialized-view refresh as a full rebuild
Main now rebuilds a materialized view completely on every refresh
(#4373): there is no incremental mode, no `full` argument and no
stable-row-ID requirement on the source. The example ran against the
SDK built from this branch (0.40.0b13) failed, because a refresh after
adding Bea writes both matching rows, not one.

The example now creates its source with the default options and expects
two rows written by the refresh, and its generated snippet is
regenerated. Separate tests cover `with_no_data` (one matching row on
the first refresh) and refreshing to an earlier source version. The
refresh page explains the full rebuild and keeps the #incremental and
#stable-row-ids anchors for the sections that replace them. Its version
note now says what the published 0.39.0 does differently, as observed
with that release.

The management, table, database, limits, architecture and data-types
pages no longer say a view's source needs stable row ids, and the
feature-engineering and tutorial summaries no longer call refreshes
incremental.
2026-10-06 20:44:06 -07:00
Brendan Clement 2e5ca5f8c5 Merge lancedb main into the documentation candidate
Brings the candidate up to main at bbc4aebe55, which rebuilds materialized views fully on refresh (#4373) and is version 0.40.0-beta.13, so the documentation and its examples can be checked against that SDK.
2026-10-06 20:32:29 -07:00
lancedb-gatefixer[bot] bbc4aebe55 fix(python): infer vector columns for sync remote search (#4409)
Sync remote string searches ignored the table's embedding function when
`vector_column_name` was omitted. `auto` silently fell back to full-text
search, while `vector` and `hybrid` failed with `No embedding function
for None`.

Resolve vector columns from the schema before creating the query
builder, using the same inference helper as local search. Automatic
string queries without embedding functions select full-text search
first, so text-only tables and tables with multiple unconfigured vector
columns remain searchable. Vector and hybrid searches still reject
ambiguous columns, infer numeric queries by dimension, and honor
explicit column selection. Structured full-text queries and empty
queries retain their existing behavior.

Regression coverage uses embedding metadata returned by a mocked remote
server rather than a mocked embedding-function lookup. It also checks
automatic and explicit full-text queries on schemas with zero, one, or
multiple vector columns and no embedding functions.

Validation after merging `main` at `87ecfeac`:

- Confirmed the original embedding and ambiguity failures before the
fix, and reproduced the automatic FTS inference failures before
restoring the fallback.
- Remote, query, hybrid, and embedding test files through the uv-managed
environment: 240 passed, 4 skipped, 9 deselected (`not slow and not
s3_test`).
- Python extension built with `uv run --extra tests --extra dev maturin
develop --extras tests,dev`.
- `ruff check .` and `ruff format .` from the repository root, using
CI's Ruff version 0.9.9.
- `cargo fmt --all`.

Fixes #4377

<!-- lance-gatekeeper-fix:v1 agent=c167c6c89d857342e5d7415b08142589
generation=1 -->

---------

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-06 19:59:21 -07:00
lancedb-gatefixer[bot] a8baecb306 fix: reject non-finite query vectors without panicking (#4410)
Remote vector serialization unwrapped `serde_json::Number::from_f64`,
which returns `None` for NaN and infinity, causing a Tokio worker panic.

Validate vectors after conversion to Float32 in the shared `nearest_to`
/ `add_query_vector` builder so local and remote queries consistently
return `Error::InvalidInput` (mapped to `ValueError` by the Python
bindings). This also rejects finite Float64 inputs that overflow
Float32. Make remote serialization fallible to protect requests
constructed directly, including single-vector queries and both remote
batch-query paths.

Validation:

- All 116 query-related Rust tests passed with the `remote` feature,
including the three new regression cases.
- The three regression cases fail with the original production code and
pass with the fix. Coverage includes NaN, positive and negative
infinity, Float16/32/64 Arrow inputs, Float64 overflow, and rejection
before any HTTP request.
- `cargo fmt --all -- --check`, `cargo check --profile ci --locked -p
lancedb --features remote --tests --examples`, and `cargo clippy
--profile ci --locked -p lancedb --features remote --tests --examples --
-D warnings` passed.

Fixes #4375

<!-- lance-gatekeeper-fix:v1 agent=97d6925d4af7cd09767da8b552c9bcf3
generation=1 -->

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-06 16:26:25 -07:00
lancedb-gatefixer[bot] 87ecfeaccd fix(python): preserve embedding functions in sync remote table creation (#4408)
Sync remote `create_table(..., embedding_functions=...)` discarded the
supplied configuration and only logged an unsupported-feature warning.
Schema-only creation therefore lost the metadata needed by `add()` to
embed text, while text-only initial data produced no vector column.

Forward the configuration to the existing async creation path, remove
the stale warning, and document the parameter. The shared path stores
the embedding metadata and generates vectors for initial data and
subsequent additions.

Add a regression test against the mocked remote HTTP API for both
schema-only and text-only creation. It checks the outgoing Arrow schema
metadata, the metadata returned by the remote table, inferred vector
types, and generated vectors during creation and `add()`.

Validation:

- Both regression cases failed before the fix because the outgoing
embedding metadata was missing, then passed after the fix.
- `uv run --extra tests --extra dev pytest
python/tests/test_remote_db.py python/tests/test_embeddings.py -q -m
'not slow and not s3_test'`: 82 passed, 4 skipped, 8 deselected.
- Repository-wide `ruff check .` and `ruff format .` passed using the
uv-managed environment; `git diff --check` passed.

Fixes #4376

<!-- lance-gatekeeper-fix:v1 agent=a6816b1f3335438bd8ad192f36395213
generation=1 -->

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-06 16:18:10 -07:00
lancedb-gatefixer[bot] 3385dc55dc fix(remote): validate schema for create_table with exist_ok (#4407)
Remote `create_table` with `exist_ok` opened an existing table without
validating the supplied schema, so Python and TypeScript silently
accepted mismatches.

Capture the request schema before consuming its data stream, compare it
with the opened table's schema, and return the same `Error::Schema` and
message as the local backend when they differ. The existing open-table
callback continues to run before validation.

Regression coverage exercises matching schemas and differences in field
name, type, and nullability, for both empty and data-backed creation
with cached and uncached table opens. All 12 mismatch cases failed
against the original implementation; all 16 cases now pass.

Validation:

- `cargo test --profile ci --features remote -p lancedb --lib
remote::db::tests`: 113 passed.
- `cargo clippy --quiet --profile ci --features remote -p lancedb
--tests --examples`: passed.
- `cargo fmt --all` and `git diff --check`: passed.

Fixes #4378

<!-- lance-gatekeeper-fix:v1 agent=5781a39ba124cf9094d36715730342b4
generation=1 -->

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-06 16:17:01 -07:00
lancedb-gatefixer[bot] 02ed5cf129 fix: require checkout before restoring remote tables (#4406)
Remote handles at the latest version have no checkout version, so
`restore()` sent `{"version":null}` and surfaced a server
deserialization error. Validate the checkout version before constructing
the request and return `Error::InvalidInput` with the same message as
local tables. This shared Rust fix covers Python sync/async and
TypeScript callers.

Add a regression test proving that restore sends no request on a fresh
handle, after `checkout_latest()`, or after a successful restore clears
checkout state. It also verifies that a valid restore sends the
checked-out version. Update the schema-cache and branch restore tests to
check out a version before restoring and require success.

Validation:

- The new regression failed against the original implementation when the
mock received a null version.
- `cargo test --locked --profile ci --features remote -p lancedb --lib
restore` — 6 tests passed.
- `cargo fmt --all` and `git diff --check` passed.
- `cargo clippy --quiet --locked --profile ci --features remote -p
lancedb --tests --examples` passed.

Fixes #4381

<!-- lance-gatekeeper-fix:v1 agent=cc67544dfcbb46d631762752d55b39e3
generation=1 -->

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-06 16:16:13 -07:00
lancedb-gatefixer[bot] 6b6d55e6c7 fix: accept updated_rows in remote update responses (#4444)
Remote update responses report their count as `updated_rows`, but the
client only recognized `rows_updated` and silently defaulted the count
to zero. Python sync/async and TypeScript both use this Rust result.

Accept `updated_rows` as a Serde alias while retaining `rows_updated`
and compatibility with older responses. Extend the remote mock test to
cover both keys, zero and missing counts, returned versions, and empty
responses, with and without a predicate.

Validation:

- Both nonzero `updated_rows` regression cases failed before the fix (0
instead of 5); all 11 focused remote tests pass after it.
- All 3 native update tests pass.
- `cargo fmt --all`
- `cargo clippy --quiet --profile ci --features remote -p lancedb
--tests --examples`

Fixes #4443

<!-- lance-gatekeeper-fix:v1 agent=423249073212c9840d96ccf6d4452905
generation=1 -->

---------

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-06 16:14:57 -07:00
XY Zhan 2bf70758a7 fix: read back the maintained-index selection a table was given (#4447)
`maintained_indexes` on a MemWAL table has three values: a named list,
`[]` for none, and `null` for every index the table has, including ones
created later. This PR makes every client read all three back as they
were set.

- **Rust remote client** (also used by the Python and Node SDKs) reads
`null` as `None`.
- **Java client** reads `null` as `null`, not as an empty list.
- **Docs** for the setter, the field and the getter describe the three
values the same way in Rust, Python, Node and Java. The generated JS
docs are regenerated to match.

## Testing

- `rust/lancedb`: 73 LSM tests pass, including one case per value. With
the decoder typed as a list, the `null` case fails.
- Java: two cases for `null` and `[]` on the read path, run by the Java
CI job.
- `cargo fmt`, `cargo clippy -D warnings` and `ruff format` are clean.
2026-10-06 19:07:10 -04:00
Brendan Clement 5546ced68d docs: regenerate snippets into docs/web/snippets
The documented command wrote to docs/snippets, the generator's default from
the old repository layout, so it created new files instead of updating the
modules the pages import, and it covered only the Python examples. Name all
three example folders and the output directory. A few modules currently
regenerate with unrelated changes, so say to review the diff.
2026-10-06 12:16:40 -07:00
Brendan Clement a2c55890db docs: list Deployment before Security so /enterprise opens the overview
Mint sends a folder URL to the first sidebar page under it unless that page
is the folder's index. With Security listed first, /enterprise opened
Authentication, while production, whose sidebar starts with the Enterprise
overview, serves the overview at /enterprise. Listing Deployment, which
starts with the overview, before Security restores that. The groups, their
pages and the redirects are otherwise unchanged.
2026-10-06 12:15:17 -07:00
Wyatt Alt dbd86ed9b7 feat: let CountPushdown see through MetadataEraserExec (#4458)
BaseTableAdapter wraps every scan in MetadataEraserExec, which reported
an unknown cardinality effect. Lance's CountPushdown only looks through
nodes that keep every row, so a SQL COUNT(*) over the adapter always
scanned, even with the rule registered. The eraser now reports Equal.

with_new_children kept the old schema and panicked when the new child's
schema differed; it now rebuilds from the child.
2026-10-06 12:02:47 -07:00
Brendan Clement 993ea90d50 docs: keep the LeRobot page's framing around its Geneva example
The previous commit restored production's sentence so the example is
attributed to Geneva. This brings back the newer page's customer-facing
framing, that feature engineering costs nothing until it is used and never
copies the dataset or touches the videos, while keeping the Geneva link and
naming the API the code calls: @udf, add_columns and backfill. The code and
its timings, measured with Geneva, are unchanged.
2026-10-06 10:17:18 -07:00
Brendan Clement 9694b26ed8 docs: say the LeRobot feature-engineering example uses Geneva
The example calls Geneva's @udf, add_columns and backfill, but the sentence
before it described lancedb computed columns and Functions, which take none
of those parameters and have no backfill. This restores the production
sentence, which names Geneva and links its UDF guide; the code and its
timings are unchanged.
2026-10-06 10:16:47 -07:00
Brendan Clement 0399d2f4da docs: redirect /training/lerobot to the LeRobot integration page
Production served the same LeRobot page at /training/lerobot and
/integrations/lerobotdataset. Only the integrations page carries over, so
the old Training URL now redirects to it instead of returning 404.
2026-10-06 10:16:47 -07:00
LanceDB RobotandWyatt Alt 17e9a657e6 chore: update lance dependency to v14.0.0-beta.1 (#4445)
Updates the Rust workspace Lance dependencies, Cargo lockfile, and Java
lance-core to
[v14.0.0-beta.1](https://github.com/lance-format/lance/releases/tag/v14.0.0-beta.1).
No compatibility fixes were required.

Validation passed: `cargo clippy --quiet --workspace --tests
--all-features -- -D warnings`, `cargo fmt --all --quiet`, and `git diff
--check`.

---------

Co-authored-by: Wyatt Alt <wyatt.alt@gmail.com>
2026-10-06 08:34:45 -07:00
Lance Release 81d52a98f8 Bump version: 0.40.0-beta.12 → 0.40.0-beta.13 2026-10-06 04:36:52 +00:00
Jack Ye 7e8f0d4982 refactor: always fully refresh materialized views (#4373)
Simplify experimental materialized views to one output-only storage
layout and one full-rebuild refresh implementation.

## Current layout

Local materialized views currently maintain incremental-refresh state
alongside the materialized values:

- an internal `__source_row_id` column for source provenance;
- `mv.definition` plus `mv.incarnation`;
- source version/timestamp, view version, and last-refresh watermarks;
- optional `mv.staging` state for table-function sources; and
- stable-row-ID requirements on the source table.

Refresh classifies source changes, appends or evicts rows when possible,
and falls back to a rebuild for unsupported deltas. Remote
create/refresh also use separate REST mutation paths.

## New layout

An MV is an ordinary Lance backing table containing only:

- the defining query's output columns;
- its current data fragments; and
- `mv.definition`, encoded as a versioned SQL envelope such as
`{"kind":"query","format":1,"query":"SELECT ..."}`.

There is no provenance column, incarnation, source/view watermark,
staging metadata, or stable-row-ID requirement. Local refresh may still
pin a source version for reproducibility, but it always recomputes the
complete result.

Full refresh streams the new result into uncommitted fragments and then
publishes a single transaction that removes every old fragment and
installs the new set. A shared conflict token prevents concurrent
replacements from both committing. This fragment-replacement primitive
is also used by Sophon's SQL worker.

## New remote create workflow

```text
Connection::create_materialized_view(...)
        -> builder renders the defining SELECT
        -> remote Database receives a CreateMaterializedViewRequest
        -> submit CREATE MATERIALIZED VIEW ... AS ... through Flight SQL
        -> retain the SQL Query handle while the Job is running
        -> consume the durable SQL-job result
        -> open the created table and read mv.definition
        -> return MaterializedView
```

Remote refresh similarly submits `REFRESH MATERIALIZED VIEW` through
Flight SQL. Cancelling either wrapper forwards cancellation to the
retained SQL query before aborting the local task, so the server
operation is not silently left running.

## API changes

- remove incremental/no-op modes and the `full` switch;
- remove distributed grouped/partitioned refresh APIs and native
vector-source MV APIs;
- keep full-refresh results across Rust, Python, and TypeScript;
- preserve list/describe/drop as object-management operations while
routing create/refresh mutations through SQL.

The storage contract is experimental and has no compatibility shim;
views using the removed layout must be recreated.
2026-10-05 21:33:34 -07:00
Brendan Clement 215f78de96 docs: read the Quickstart image from where the examples now live
The TypeScript and Rust Quickstarts read the image from ../../docs/static,
the layout before the documentation moved into this repository. The file is
docs/web/static/assets/images/quickstart/sir-lancelot.jpg, so the TypeScript
test failed with ENOENT and the Rust example panicked at the read. Both now
resolve the image from the example's own directory (__dirname and
CARGO_MANIFEST_DIR), and the two Quickstart exports are regenerated with
docs/web-tests/mdx_snippets_gen.py.
2026-10-05 20:27:11 -07:00
Brendan Clement 799c66bac8 docs: build the Rust examples with ethnum 1.5.3
ethnum 1.5.2, which jsonb brings in through lance-arrow, transmutes () into
TryFromIntError and no longer compiles on Rust 1.97.0, the toolchain this
repository pins, so none of the Rust examples built. 1.5.3 builds the error
from a failed conversion instead. Only that lockfile entry changes; lancedb
stays at 0.31.0.
2026-10-05 20:27:11 -07:00
Colin Patrick McCabe d864e7198f feat!: list_databases returns an iterator (#4442)
CatalogConnection.list_databases should return an iterator so that users
don't have to manually re-implement pagination. For those who do want
more control over pagination, add num_page_results and page_token to the
Iterator object, and also allow the iterator object to be created at a
specific page token.
2026-10-05 19:41:53 -07:00
Brendan Clement d40ca61895 docs: redirect /search/sql to the SQL reference
Production serves its "Query with SQL" page at /search/sql, and the same
page at /search/sql/index; both URLs return that page on
docs.lancedb.com. Only the /index form was redirected to /sql, where that
guide now lives, so the canonical URL would have 404ed. It now redirects
to the same destination.
2026-10-05 16:37:21 -07:00
Brendan Clement bad783aff9 docs: add the FineWeb EDU and DROID demos to the gallery
Carries over production's #368 (deploy-freeze 113db11c), which landed after
this branch's gallery was split into a page per demo. Each demo gets a page
in that layout with production's card, badges and link, and a row in the
overview table and the sidebar. The two hero images are byte-identical to
production's.
2026-10-05 16:35:56 -07:00
Brendan Clement b3f8a035df docs: link to the contact page instead of contact@lancedb.com
Carries over production's #360 (deploy-freeze 78d55c2) where it was only
partly ported. The navbar's Support link still opened
mailto:contact@lancedb.com, and the home page linked the contact page but
showed the email address as link text. Both now match production. The
other passages #360 changed are already ported at their new paths.
2026-10-05 16:35:56 -07:00
ccmao1130 f4544628ba fix: add UTM to reverie link, remove cloud in banner (#4446)
- Add UTM to Reverie link for tracking
- Remove "Try LanceDB Cloud" in banner
2026-10-05 15:19:08 -07:00
ccmao1130 6bdfe73604 fix: add reverie banner to readme (#4346)
Add Reverie banner to the top of README until event ends.

Additionally, I also removed the "LanceDB Cloud" skinny banner since
we're not promoting that right? Should we modify the larger LanceDB
modify to not mention "Try LanceDB Cloud"?
2026-10-05 15:03:16 -07:00
Brendan Clement a2803e1a02 docs: scope the materialized-view note to the SDK it was tested on
The note dated the new behavior to "SDK 0.40", but it was verified on the
development SDK 0.40.0b12 built from main, and no stable 0.40 has been
released. The note now names that build and keeps the comparison with
the published 0.39.0, which creates the view empty, has no with_no_data,
and writes both matching rows on the first refresh.
2026-10-05 15:00:20 -07:00
Brendan Clement df4605850d docs: keep the Enterprise Function test to objects it creates
The opt-in Enterprise walkthrough overwrote the table `function_demo`,
registered the Function `double`, then dropped both. On this SDK
drop_function removes the named Function, not only the version this run
created, so a run against a shared database could replace or remove
existing objects.

The walkthrough snippets keep their names. The test registers a copy of
`double` under a name unique to the run, creates the table under such a
name, and drops only those two objects. The table is no longer created
with mode="overwrite", so even a name collision cannot replace an
existing table. The remote test has not been run.
2026-10-05 15:00:20 -07:00
Brendan Clement ec44eb72fa docs: say which Function outputs may be nullable
The page said every Function output must be non-nullable. On this SDK
only a scalar output must be. A named-struct output may declare nullable
fields: whether a row has a result at all is the struct's own validity,
which Enterprise keeps in a separate internal column when it expands the
result into sibling columns.

test_function_output_nullability checks both rules against the SDK,
including that a struct declared as a single nullable field is refused.
2026-10-05 15:00:20 -07:00
Brendan Clement ac69de17b3 docs: say how to drop a Function
maintenance/background-jobs.mdx links to /management/function#drop, which
did not exist. The section follows drop_function and drop_function_async
on main: dropping removes the name and its object, and deleting the
content can finish later as a background job.
2026-10-05 14:23:40 -07:00
Brendan Clement 8cdff48859 docs: repair six links to anchors that no longer exist
Found by `mint broken-links --check-anchors` on the assembled site. Three
point at sections that were renamed or moved: the tag-versioning heading,
the branches comparison table, and the table-creation patterns, which now
live on the Create a table page. Three named sections that no longer exist
and now link to the page they were on.
2026-10-05 14:23:23 -07:00
Brendan Clement 6367f7a0de docs: describe refresh and retries the same way on every page
Five pages still said a refresh never revisits a filled row and that a
changed input needs the column dropped and declared again. Since
lancedb#4161 a refresh also recomputes rows whose inputs changed, so the
quickstart, the feature-engineering overview, Guarantees, and the SQL
REFRESH and UPDATE pages now say that.

Retry claims are qualified the same way. A local refresh commits the column
once, and a deployment's job commits finished batches. A retry fills what is
still empty or stale, but can recompute values that were already written (a
refresh whose input record was not saved recomputes next time), so no page
promises that a retry costs only the unfinished rows.
2026-10-05 14:12:12 -07:00
Brendan Clement 69f11c259d docs: show that creating a materialized view computes its rows
Since lancedb#4180, create_materialized_view runs the initial refresh
before it returns (with_no_data=True skips it), so the page's first manual
refresh now writes 0 rows, not 1. The example now reads the populated view
and refreshes after a source change, and its snippets come from
docs/web-tests/py/test_materialized_view.py. A note scopes the behavior:
0.39 and earlier create the view empty.

Pages that said a refresh computes the rows now say it brings them up to
date, and the SQL note no longer says an incremental refresh covers only
added rows.
2026-10-05 14:10:44 -07:00
Brendan Clement 72517dd0f6 docs: build the progress message from template literals
Biome's useTemplate rule flagged the restored example's string
concatenation. The message it logs is unchanged.
2026-10-05 14:07:59 -07:00
Brendan Clement b87c4de53b docs: regenerate the vector-index snippets the page imports
Porting the upstream changes replaced snippets/indexing.mdx with a hand
copy from lancedb/docs, which dropped six exports the vector-index page
still imports (`mint validate` warns on each) and added
PyQuantizationCustomParams, which had no source here.

The quantization test region is ported from lancedb/docs and the module
is regenerated, so every export comes from a test again. The regenerated
PyQuantizationCustomParams matches the copy byte for byte. Also fixes
"convetion" and "entires" on the page.
2026-10-05 14:07:14 -07:00
Brendan Clement 08dd402473 ci: accept the docs' product name and examples in the spell check
The migrated docs trip typos on text that is not misspelled: Superlinked's
inference engine (SIE) and its `sie-lancedb` package, the conventional
`fiftyone as fo` and `torchvision.io as tio` import aliases, the substring
query "nce" in the n-gram search example, and garbled OCR output quoted
verbatim in the VLM fine-tuning tutorial.

SIE becomes a dictionary word. The others are ignored only in those
contexts, so the same strings are still flagged in prose.
2026-10-05 14:04:57 -07:00
Brendan Clement 07fc8f46d6 Merge lancedb main a68c7be2 into the docs candidate 2026-10-05 14:04:47 -07:00
Brendan Clement 41ec678699 docs: fix the two snippet imports Mint cannot resolve
Two pages imported PySchemaAddSetup under the alias SchemaAddSetup, and
Mint resolved only the first, failing `mint validate` on
management/table.mdx. Both pages now import it unaliased.

TsAddProgress was added to the generated tables snippets by hand in
lancedb/docs#243 and dropped by the next regeneration, leaving
ingestion/insert.mdx with a missing import. Its example is restored
unchanged as a test in docs/web-tests/ts/tables.test.ts, which checks
that the callback reports the finished write.
2026-10-05 13:27:53 -07:00
Brendan Clement c2c16b60b9 docs: fix two typos the spell check found
"explictly" and "Additionaly", in snippet sources and their generated
snippets. integrations.mdx is updated in place: regenerating it whole
would also drop PyRerankingWatsonxUsage, which has no source.
2026-10-05 13:27:53 -07:00
Brendan Clement 3d187ddf58 docs: point the docs tests at the moved static assets
The quickstart and Camelot tests still read docs/static/..., which moved
to docs/web/static/..., so both failed with FileNotFoundError.
2026-10-05 13:27:53 -07:00
Brendan Clement b218633e36 docs: read a materialized view's table and definition as properties
`view.table()` and `view.definition()` raise TypeError on a synchronous
view; both are properties. An async view reads its definition with
`await view.definition()`.
2026-10-05 13:27:53 -07:00
Brendan Clement c22686e3c8 docs: say that a refresh recomputes rows whose inputs changed
Since lancedb#4161 a refresh recomputes rows whose inputs changed, and it
records what it computed from in a second, metadata-only commit, so the
example's version is 4. A local refresh commits once, so a failure keeps
none of its values; the page no longer says each row commits as it
completes.
2026-10-05 13:27:53 -07:00
Brendan Clement 6389784dde docs: apply a registered Function version in the Function guide
The guide applied the local decorated callable to `table["value"]`, which
raises TypeError: a table is not subscriptable, and add_columns takes an
application of a registered version, not the callable's result.

The guide now walks one example from definition to filled column: define
`double`, call it locally, connect to Enterprise, create a table whose
`value` column matches the parameter's type and nullability, register the
function, apply `version(value=col("value"))`, refresh, wait, and read the
values back. Its snippets come from docs/web-tests/py/test_function.py.

The local tests in that file check what `@udf` sends for registration, how
a registered version binds a column, and that a local connection refuses
both registration and Function columns. The Enterprise walkthrough runs
only when LANCEDB_URI, LANCEDB_API_KEY and LANCEDB_HOST_OVERRIDE are set.

The page also stops promising that a retry after a failed refresh costs
only the unfinished rows.
2026-10-05 13:27:53 -07:00
Will JonesandClaude a68c7be202 feat(node): accept ArrayBuffer, Blob/File, and URL as blob column inputs (#4313)
Closes #4270.

## Summary

Blob v2 columns now accept more of the containers TypeScript code
commonly has, both as the column value and inside `{ data }` / `{ uri
}`:

| Input | Handling |
|---|---|
| `ArrayBuffer` | `new Uint8Array(value)`, no copy |
| `URL` | stored as `value.href` |
| `Blob` / `File` | `await value.arrayBuffer()` in the async write
paths: `createTable`, `add`, `mergeInsert` |

`makeArrowTable` is synchronous, so it can't read a `Blob`. Given one,
it throws an error that names the field and row and points to the async
APIs or `new Uint8Array(await value.arrayBuffer())`. It does not write a
null blob.

### Types
`BlobInput` is now the accepted input type. It is widened to the types
above and exported from the package entry point with `BlobData` and
`BlobUri`, so callers can annotate rows and `tsc` catches bad inputs.
The struct forms are a union that requires exactly one of `data` /
`uri`. The old normalized `{ data, uri }` shape is renamed to
`BlobValue` (internal).

### Implementation
- `blob.ts`: `normalizeBlobInput` (sync: `ArrayBuffer`/`URL`),
`resolveBlobInput` (async: `Blob`/`File`). `coerceBlobValue` normalizes
first.
- `arrow.ts`: `mapBlobInputs` walks only the blob positions in the
schema, including blobs nested in structs and lists. It copies records
and arrays only where a value changed, so caller data is never mutated.
`resolveBlobInputs` runs before `makeArrowTable` in `convertToTable`
(used by `add` / `mergeInsert`) and in `createTable`. Each distinct
`Blob` is read once.
- `makeArrowTable` now coerces every blob value to the full `{ data, uri
}` struct **before** schema inference. This also fixes two bugs that
existed before this change:
  - Rows mixing plain bytes with `{ data }` failed inference.
- A `{ uri }`-only struct produced a blob struct missing its `data`
child.

  Blob validation errors now include the field path and row.
- Also fixed along the way:
- `add` / `mergeInsert` on a table with an embedding function rejected
most blob values, because `ensureNestedFieldsExist` filled blob columns
in like ordinary structs. It now skips them.
- With a schema, a struct field that is `null` in one row and a record
in a later row failed inference. Primitives and arrays given for a
struct field are now rejected instead of being written as an all-null
struct.
- Blob structs with keys other than `data` / `uri` are rejected, which
catches typos. Class instances with `data` / `uri` are handled like
plain objects.

## Testing
- Unit tests in `__test__/blob.test.ts`: coercion of the new types,
rejection and error messages for `Blob` in the sync path, nested lists
and structs, `resolveBlobInputs` (only blob columns touched, caller data
untouched, shared `Blob` read once).
- Table tests in `__test__/table.test.ts`:
- `createTable`, `add`, and `mergeInsert` round-trip `ArrayBuffer` /
`Blob` / `File` bytes through `fetchBlobs`.
- `URL` and `{ uri: URL }` are added to the external-blob round-trip
test from #4317 (`allowExternalBlobOutsideBases`).
- Full `jest` suite passes locally after the rebase (938 passed). `pnpm
lint` is clean and `pnpm run docs` has been regenerated.

Streaming inputs (`ReadableStream`, Node `Readable`, async iterables)
remain out of scope, as the issue says.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_012U4KdHofT5edv3LcXHXbLv

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-05 12:35:00 -07:00
Will JonesandClaude Opus 5.5 11b679a2db ci: add critical fixes section to release notes (#4361)
Adds a "🚨 Critical Fixes" section to the release notes, directly below
Highlights, for PRs labeled `critical-fix`.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 12:25:47 -07:00
Aviral Saxena 5f0bb98e90 fix(python): use exact integer math for list_versions timestamps (#4426)
Refs #4404.

AsyncTable.list_versions split the nanosecond timestamp with float
division/modulo (`ts // 1e9`, `ts % 1e9`).
At ~1.8e18 a float can't hold every integer, so the microseconds drifted
(.274000 came back as .273999).

Use `divmod(ts, 1_000_000_000)` and integer // 1000 instead.

Only the precision fix is included here. Timezone-aware UTC (option 1 in
#4404) is on hold for now,
and I can add it here or in a follow-up depending on what they prefer.

Added test_list_versions_timestamp_precision using the value from the 
issue (1790989429274000000), expecting microsecond == 274000.
2026-10-05 11:15:46 -07:00
Xuanwo 61a285f590 fix: preserve Function dependency errors in column operations (#4434)
Function column declarations and refreshes can return HTTP 404 when the
referenced Function has been deleted. The SDK currently translates those
responses into `TableNotFound`, hiding the server diagnostic and making
an existing table appear missing.

Preserve the HTTP error, status, and request ID for these two operations
while retaining schema-cache invalidation. Ordinary table operations
keep their existing `TableNotFound` behavior.
2026-10-05 14:34:32 +08:00
lancedb-gatefixer[bot] 7f5933594f fix(python): reject empty query vectors before column inference (#4415)
Empty list and NumPy vector queries were validated too late: local
search inferred a vector column first, producing misleading schema
errors, while remote search indexed `vector[0]` and raised `IndexError`.

Add a shared empty-vector check before column inference and query
creation, and validate direct vector-builder inputs. Local and remote
sync search now raise `ValueError: Query vector must not be empty` for
these inputs.

Validation:

- All 26 new regression cases failed on the original code and pass with
the fix, covering list/NumPy inputs, automatic/explicit vector search,
inferred/explicit column names, one/two local vector columns, and remote
search before query submission.
- After merging current `main`, all 32 focused cases passed, covering
these regressions and upstream async searches without a query.
- The query, table, remote, utility, hybrid-query, and database suites
passed in the rebuilt uv environment: 541 passed, 1 skipped, 1 slow test
deselected.
- `ruff check .`, `ruff format .`, and `cargo fmt --all` passed from the
repository root.

Fixes #4389

<!-- lance-gatekeeper-fix:v1 agent=f1f4875090ef391bb1aa912dd54026dc
generation=1 -->

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-03 21:30:13 -07:00
lancedb-gatefixer[bot] 3e0a1a8780 fix: reject zero vector search probes across SDKs (#4418)
`nprobes(0)` bypassed the validation used by the minimum and maximum
probe setters, allowing zero into query requests and producing
inconsistent local and remote results. Sync Python could additionally
interpret the zero maximum as an unbounded search.

Reject zero in the Rust vector-query builder and propagate its input
error through the Python vector/hybrid and Node bindings. Validate
nonpositive counts in the sync Python vector and hybrid builders so
every SDK and backend reports `nprobes must be greater than 0` before
execution. Update the Rust examples and document the positive-count
requirement.

Regression tests cover local and remote vector/hybrid builders,
rejection before remote query requests, promised TypeScript query
vectors, and positive counts replacing both probe bounds.

Validation:

- Rust probe regression tests: 2 passed.
- Focused Python query, remote, hybrid, and serialization tests: 22
passed. The four sync regression cases fail with the original setters.
- Focused TypeScript indexed local and mocked remote tests: 2 passed.
- Workspace `cargo check --features remote --tests --examples` and
Clippy passed.
- Rust formatting, Python formatting/lint, and TypeScript
build/lint/docs passed. Repository-wide `ruff check .` reports 29
existing errors in unchanged CI scripts; `ruff check python` passes.

Fixes #4388

BREAKING CHANGE: Rust `VectorQuery::nprobes` now returns `Result<Self>`
instead of `Self`; callers must handle the result, as with the existing
minimum/maximum probe setters.

<!-- lance-gatekeeper-fix:v1 agent=e92fda5a212c7f9e80fa55e7b4e4634d
generation=1 -->

Co-authored-by: Gatefixer <313497061+lancedb-gatefixer[bot]@users.noreply.github.com>
2026-10-03 21:29:47 -07:00