{"record":{"id":"652611378069abfe","repo":"cocoindex-io/cocoindex","slug":"record-type-must-be-a-record-type-dataclass-name","errorCode":null,"errorMessage":"record_type must be a record type (dataclass, NamedTuple, Pydantic model), got {type(record_type)}","messagePattern":"record_type must be a record type \\(dataclass, NamedTuple, Pydantic model\\), got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/bigquery/_target.py","lineNumber":148,"sourceCode":"\n    @classmethod\n    async def from_class(\n        cls,\n        record_type: type[RowT],\n        primary_key: list[str],\n        *,\n        column_overrides: dict[str, BigQueryType] | None = None,\n    ) -> \"TableSchema[RowT]\":\n        \"\"\"\n        Create a TableSchema from a record type.\n\n        Args:\n            record_type: A dataclass, NamedTuple, or Pydantic model.\n            primary_key: List of column names that form the primary key.\n            column_overrides: Optional per-column BigQueryType overrides.\n        \"\"\"\n        if not is_record_type(record_type):\n            raise TypeError(\n                f\"record_type must be a record type (dataclass, NamedTuple, Pydantic model), \"\n                f\"got {type(record_type)}\"\n            )\n        columns = await cls._columns_from_record_type(record_type, column_overrides)\n        return cls(columns, primary_key, row_type=record_type)\n\n    @staticmethod\n    async def _columns_from_record_type(\n        record_type: type,\n        column_overrides: dict[str, BigQueryType] | None,\n    ) -> dict[str, ColumnDef]:\n        \"\"\"Convert a record type to a dict of column name to ColumnDef.\"\"\"\n        record_info = RecordType(record_type)\n        columns: dict[str, ColumnDef] = {}\n\n        for field in record_info.fields:\n            override = column_overrides.get(field.name) if column_overrides else None\n            type_info = analyze_type_info(field.type_hint)","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/bigquery/_target.py#L130-L166","documentation":"from_class derives the target's columns from the record type's fields, which requires a dataclass, NamedTuple, or Pydantic model. If record_type is any other type (str, dict, plain class, None), is_record_type fails and a TypeError is raised naming the actual type received.","triggerScenarios":"Calling table_target(..., record_type='MyRow') passing the class name as a string; passing a dict of column specs instead of a typed record; passing a plain (non-dataclass) class or a TypedDict.","commonSituations":"Confusing TypedDict with NamedTuple; forgetting the @dataclass decorator; passing an instance instead of the class; stringly-typed configuration of record types.","solutions":["Pass an actual dataclass, NamedTuple, or Pydantic model class (not a string, dict, or instance).","Add the @dataclass decorator if you intended a dataclass but forgot it.","Convert a TypedDict to NamedTuple or dataclass, or use Pydantic BaseModel.","Ensure you pass the class object itself, e.g. Row, not Row() or 'Row'."],"exampleFix":"// before\ntarget = table_target(client, \"proj.ds.tbl\", {\"id\": \"INT64\"}, primary_key=[\"id\"])\n\n// after\n@dataclass\nclass Row:\n    id: int\n    name: str\ntarget = table_target(client, \"proj.ds.tbl\", Row, primary_key=[\"id\"])","handlingStrategy":"type-guard","validationCode":"import dataclasses\nassert dataclasses.is_dataclass(Row), \"record_type must be a dataclass/NamedTuple/Pydantic model\"","typeGuard":"def is_record_type(t: object) -> bool:\n    import dataclasses\n    if dataclasses.is_dataclass(t):\n        return True\n    if isinstance(t, type) and issubclass(t, tuple):\n        return hasattr(t, \"_fields\")\n    try:\n        from pydantic import BaseModel\n        return isinstance(t, type) and issubclass(t, BaseModel)\n    except ImportError:\n        return False","tryCatchPattern":"try:\n    target = table_target(client, table, record_type, primary_key=pk)\nexcept TypeError as e:\n    logger.error(\"bad record_type: %s\", e)\n    raise","preventionTips":["Pass the class object, never its name or an instance.","Always decorate intended dataclasses with @dataclass.","Prefer NamedTuple/dataclass over TypedDict for table row types."],"tags":["python","bigquery","type-error","record-type"],"backgroundTag":"type-mismatch","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}