cocoindex-io/cocoindex · error · TypeError

record_type must be a record type (dataclass, NamedTuple, Py

Error message

record_type must be a record type (dataclass, NamedTuple, Pydantic model), got {type(record_type)}

What it means

from_class builds the table schema from a record type, which must be a dataclass, NamedTuple, or Pydantic model (checked via is_record_type). Anything else (dict, plain class, typing construct, None) cannot be introspected into columns, so a TypeError is raised with the actual type.

Source

Thrown at python/cocoindex/connectors/lancedb/_target.py:277

        record_type: type[RowT],
        primary_key: list[str],
        *,
        column_specs: dict[str, LanceType | res_schema.VectorSchemaProvider]
        | None = None,
    ) -> "TableSchema[RowT]":
        """
        Create a TableSchema from a record type (dataclass, NamedTuple, or Pydantic model).

        Python types are automatically mapped to PyArrow types.

        Args:
            record_type: A record type (dataclass, NamedTuple, or Pydantic model).
            primary_key: List of column names that form the primary key.
            column_specs: Optional dict mapping column names to LanceType or
                          VectorSchemaProvider to override the default type mapping.
        """
        if not is_record_type(record_type):
            raise TypeError(
                f"record_type must be a record type (dataclass, NamedTuple, Pydantic model), "
                f"got {type(record_type)}"
            )
        columns = await cls._columns_from_record_type(record_type, column_specs)
        return cls(columns, primary_key, row_type=record_type)

    @staticmethod
    async def _columns_from_record_type(
        record_type: type,
        column_specs: dict[str, LanceType | res_schema.VectorSchemaProvider] | None,
    ) -> dict[str, ColumnDef]:
        """Convert a record type to a dict of column name -> ColumnDef."""
        record_info = RecordType(record_type)
        columns: dict[str, ColumnDef] = {}

        for field in record_info.fields:
            spec = column_specs.get(field.name) if column_specs else None
            type_info = analyze_type_info(field.type_hint)

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Pass a dataclass, NamedTuple, or Pydantic model class: decorate your class with @dataclass if needed.
  2. Ensure you pass the type itself, not an instance.
  3. Verify with `is_record_type(MyRecord)` before calling from_class.

Example fix

// before
await target.from_class({"id": int, "vec": ...}, primary_key=["id"])
// after
@dataclass
class MyRecord:
    id: str
    vec: np.ndarray
await target.from_class(MyRecord, primary_key=["id"], column_specs={"vec": VectorSchemaProvider(size=768)})
Defensive patterns

Strategy: type-guard

Validate before calling

from cocoindex.connectors.lancedb._target import is_record_type
if not is_record_type(MyRecord):
    raise TypeError("from_class needs a dataclass/NamedTuple/Pydantic model class")

Type guard

def is_record(obj: object) -> bool:
    import dataclasses
    return isinstance(obj, type) and (
        dataclasses.is_dataclass(obj)
        or (issubclass(obj, tuple) and hasattr(obj, "_fields"))
        or hasattr(obj, "model_fields")
    )

Try / catch

try:
    target = await LanceDbTarget.from_class(record_type, primary_key=["id"])
except TypeError as e:
    if "record_type must be a record type" in str(e):
        ...  # pass the class, decorated appropriately
    raise

Prevention

When it happens

Trigger: Calling `LanceDbTarget.from_class(record_type, ...)` with a non-record value: a plain class not decorated with @dataclass, a dict of fields, a typing construct, or accidentally passing an instance instead of the class.

Common situations: Forgetting the @dataclass decorator; passing the record instance rather than its type; migrating from another connector whose API accepted dicts.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/797e31df366ba43e. Report an issue: GitHub.