diff --git a/python/python/lancedb/pydantic.py b/python/python/lancedb/pydantic.py index c4dedc0e6..1ab6e6fcc 100644 --- a/python/python/lancedb/pydantic.py +++ b/python/python/lancedb/pydantic.py @@ -153,6 +153,16 @@ def Vector( return FixedSizeList +def _raise_bare_vector_error(*_args): + raise TypeError("Vector must be parameterized with a dimension, e.g. Vector(128).") + + +# Pydantic v1 and v2 otherwise treat the bare Vector factory as a field validator +# and inspect its signature, which produces misleading errors about internal types. +setattr(Vector, "__get_validators__", _raise_bare_vector_error) +setattr(Vector, "__get_pydantic_core_schema__", _raise_bare_vector_error) + + def MultiVector( dim: int, value_type: pa.DataType = pa.float32(), nullable: bool = True ) -> Type: diff --git a/python/python/tests/test_pydantic.py b/python/python/tests/test_pydantic.py index e1d533784..db93d7c64 100644 --- a/python/python/tests/test_pydantic.py +++ b/python/python/tests/test_pydantic.py @@ -415,6 +415,17 @@ def test_nullable_vector(): assert schema == pa.schema([pa.field("vec", pa.list_(pa.float32(), 16), True)]) +def test_bare_vector_raises_clear_error(): + namespace = { + "__name__": "test_model_without_pyarrow", + "LanceModel": LanceModel, + "Vector": Vector, + } + + with pytest.raises(TypeError, match=r"Vector must be parameterized.*Vector\(128\)"): + exec("class TestModel(LanceModel):\n vector: Vector", namespace) + + def test_fixed_size_list_field(): class TestModel(pydantic.BaseModel): vec: Vector(16)