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

The `table_target`/`from_class` factory for the SQLite connector requires `record_type` to be a supported record type (dataclass, NamedTuple, or Pydantic model). The library validates this with `is_record_type()` and raises `TypeError` when any other value (e.g. a plain class, dict, or instance) is passed, because it relies on record introspection to derive column names and types.

Source

Thrown at python/cocoindex/connectors/sqlite/_target.py:358

        record_type: type[RowT],
        primary_key: list[str],
        *,
        column_overrides: dict[str, SqliteType | 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 SQLite types.

        Args:
            record_type: A record type (dataclass, NamedTuple, or Pydantic model).
            primary_key: List of column names that form the primary key.
            column_overrides: Optional dict mapping column names to SqliteType 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_overrides)
        return cls(columns, primary_key, row_type=record_type)

    @staticmethod
    async def _columns_from_record_type(
        record_type: type,
        column_overrides: dict[str, SqliteType | 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 rec_field in record_info.fields:
            override = (

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Annotate the class with `@dataclass` (or make it a NamedTuple / subclass a Pydantic BaseModel) and pass the class itself, not an instance
  2. If you cannot change the type, build the table schema with explicit `SqliteColumn` definitions instead of deriving them from a record type
  3. Check that the import points at the class, not a module or instance variable

Example fix

// before
row = MyRow(id=1, text="hi")
target = sqlite.table_target("docs", record_type=row, primary_key=["id"])
// after
@dataclass
class MyRow:
    id: int
    text: str

target = sqlite.table_target("docs", record_type=MyRow, primary_key=["id"])
Defensive patterns

Strategy: type-guard

Validate before calling

import dataclasses
from cocoindex.connectors.sqlite import _target  # or use the public helper
assert dataclasses.is_dataclass(MyRow) or issubclass(MyRow, tuple) or issubclass(MyRow, BaseModel)

Type guard

def is_record_type_ok(rt: object) -> bool:
    import dataclasses
    from pydantic import BaseModel
    return (
        isinstance(rt, type)
        and (dataclasses.is_dataclass(rt) or issubclass(rt, tuple) or issubclass(rt, BaseModel))
    )

Try / catch

try:
    target = sqlite.table_target("docs", record_type=MyRow, primary_key=["id"])
except TypeError as e:
    if "record_type must be a record type" in str(e):
        raise ValueError("Pass the record class (dataclass/NamedTuple/Pydantic), not an instance") from e
    raise

Prevention

When it happens

Trigger: Calling `SqliteTarget.from_class(record_type=...)` (or `table_target(...)` with a record-based schema) with a value that is not a dataclass, NamedTuple, or Pydantic model — e.g. a plain `class`, a `dict`, a TypedDict, or an *instance* of a dataclass instead of the class itself.

Common situations: Developers pass a TypedDict (looks record-like but is not supported), pass an instantiated row object instead of the type, or use a plain class without the `@dataclass` decorator. Also common when a refactor changes a dataclass into a regular class or attrs model.

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/8531f2dbbbb5138e. Report an issue: GitHub.