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() maps a Python record type (dataclass, NamedTuple, or Pydantic model) to zvec collection columns. If the passed object is not one of these recognized record types (checked via is_record_type), a TypeError is raised because column inference cannot proceed.
Source
Thrown at python/cocoindex/connectors/zvec/_target.py:496
record_type: type[RowT],
primary_key: list[str],
*,
column_overrides: dict[
str,
ZvecType | ZvecVectorDef | ZvecFtsType | res_schema.VectorSchemaProvider,
]
| None = None,
) -> "CollectionSchema[RowT]":
"""Build a CollectionSchema from a record type.
Args:
record_type: A dataclass, NamedTuple, or Pydantic model.
primary_key: Exactly one column name. Its value becomes the document
id (converted to ``str``).
column_overrides: Optional per-column type/vector overrides.
"""
if not is_record_type(record_type):
raise TypeError(
"record_type must be a record type (dataclass, NamedTuple, "
f"Pydantic model), got {type(record_type)}"
)
if len(primary_key) != 1:
raise ValueError(
"zvec collections require exactly one primary key column "
f"(mapped to the document id), got {primary_key}."
)
record_info = RecordType(record_type)
columns: dict[str, _Column] = {}
for fld in record_info.fields:
override = column_overrides.get(fld.name) if column_overrides else None
columns[fld.name] = await _resolve_column(fld.name, fld.type_hint, override)
return cls(columns, primary_key[0], row_type=record_type)
def _metric_type(metric: str) -> Any:View on GitHub (pinned to e84aa99b32)
Solutions
- Decorate the class with @dataclasses.dataclass, or use typing.NamedTuple, or use a Pydantic BaseModel.
- Pass the class itself, not an instance.
- Check that is_record_type(record_type) returns True before calling from_class.
Example fix
// before
schema = RecordTarget.from_class({"id": str, "vec": list[float]}, primary_key=("id",))
// after
@dataclass
class Doc:
id: str
vec: list[float]
schema = RecordTarget.from_class(Doc, primary_key=("id",)) Defensive patterns
Strategy: type-guard
Validate before calling
import dataclasses
if not (dataclasses.is_dataclass(record_type) or issubclass(record_type, tuple) or issubclass(record_type, BaseModel)):
raise TypeError("need dataclass/NamedTuple/Pydantic model") Type guard
def is_record_type(t: Any) -> bool:
import dataclasses
return dataclasses.is_dataclass(t) or (isinstance(t, type) and issubclass(t, tuple)) or (isinstance(t, type) and issubclass(t, BaseModel)) Try / catch
try:
target = RecordTarget.from_class(record_type, primary_key=("id",))
except TypeError as e:
logging.error("unsupported record type: %s", e) Prevention
- Always decorate record classes with @dataclass or subclass NamedTuple/BaseModel.
- Pass the class, not an instance, to from_class.
- Avoid TypedDict for record schemas.
When it happens
Trigger: Calling RecordTarget.from_class() with a plain dict, TypedDict, plain class, tuple, or an unannotated class instead of a dataclass/NamedTuple/Pydantic model.
Common situations: Using a TypedDict (not supported as a record type here); passing a Pydantic v1 model when only v2 is detected; passing the class instance instead of the class; forgetting @dataclass decorator.
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
- Unsupported record type: {self.record_type}
- record_type must be a record type (dataclass, NamedTuple, Py
- record_type must be a record type (dataclass, NamedTuple, Py
- record_type must be a record type (dataclass, NamedTuple, Py
- record_type must be a record type (dataclass, NamedTuple, Py
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/19ae81725b2fe54d.
Report an issue: GitHub.