From 256db55a5195bba35b9e240932d17d580589009b Mon Sep 17 00:00:00 2001 From: Joaquin Hui Gomez <132194176+joaquinhuigomez@users.noreply.github.com> Date: Mon, 26 Oct 2026 09:02:36 +0000 Subject: [PATCH] fix(python)!: align RemoteDBConnection.create_table parameter order (#4608) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `RemoteDBConnection.create_table` orders its parameters `(name, data, schema, on_bad_vectors, fill_value, mode, exist_ok, ...)`, while `DBConnection`, `LanceDBConnection` and `LanceNamespaceDBConnection` all use `(name, data, schema, mode, exist_ok, on_bad_vectors, fill_value, ...)`. Since `RemoteDBConnection` subclasses `DBConnection`, identical positional calls bind to different parameters: switching a working script from `lancedb.connect(path)` to `lancedb.connect("db://...")` silently turns `mode="overwrite"` into `on_bad_vectors="overwrite"` and `exist_ok=True` into `fill_value=True`, and nothing client-side validates either. `inspect.signature(...).bind(None, "t", data, None, "overwrite", True)` shows it deterministically, no cloud needed. This reorders the remote signature to match the other three; every parameter keeps its own existing default (including the remote's `mode=None`, which its body relies on), and the body already forwards by keyword so nothing else changes. The new test asserts positional parity with `DBConnection` through `embedding_functions` and fails on `main`. Blast radius, stated plainly: only remote callers passing four or more positional arguments are affected — positions 4–7 move; positions 1–3 and 8 are unchanged and keyword callers are unaffected. No in-repo caller passes more than two positionals. Anyone relying on the current order was relying on behaviour that contradicts the documented base contract and diverges from local connections. Not added here: the `storage_options`/`data_storage_version`/`enable_v2_manifest_paths` parameters the remote signature still lacks. --------- Co-authored-by: Xuanwo --- python/python/lancedb/remote/db.py | 4 ++-- python/python/tests/test_remote_db.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/python/python/lancedb/remote/db.py b/python/python/lancedb/remote/db.py index 62d00f284..c11e01ff4 100644 --- a/python/python/lancedb/remote/db.py +++ b/python/python/lancedb/remote/db.py @@ -569,10 +569,10 @@ class RemoteDBConnection(DBConnection): name: str, data: DATA = None, schema: Optional[Union[pa.Schema, LanceModel]] = None, - on_bad_vectors: str = "error", - fill_value: float = 0.0, mode: Optional[str] = None, exist_ok: bool = False, + on_bad_vectors: str = "error", + fill_value: float = 0.0, embedding_functions: Optional[List[EmbeddingFunctionConfig]] = None, *, namespace_path: Optional[List[str]] = None, diff --git a/python/python/tests/test_remote_db.py b/python/python/tests/test_remote_db.py index c1db92948..95da3eba2 100644 --- a/python/python/tests/test_remote_db.py +++ b/python/python/tests/test_remote_db.py @@ -5,6 +5,7 @@ import contextlib from datetime import timedelta import http.server import io +import inspect import json import multiprocessing as mp import pickle @@ -765,6 +766,15 @@ def test_create_table_embedding_functions(with_schema): ] +def test_create_table_positional_parameters_match_base_contract(): + from lancedb.db import DBConnection + from lancedb.remote.db import RemoteDBConnection + + expected = list(inspect.signature(DBConnection.create_table).parameters)[:9] + actual = list(inspect.signature(RemoteDBConnection.create_table).parameters)[:9] + assert actual == expected + + def test_create_table_exist_ok(): def handler(request): if request.path == "/v1/table/test/create/?mode=exist_ok":