{"record":{"id":"59bc3da2e3579556","repo":"cocoindex-io/cocoindex","slug":"record-type-must-be-a-record-type-dataclass-name-59bc3d","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":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/snowflake/_target.py","lineNumber":141,"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, SnowflakeType] | 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 SnowflakeType 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, SnowflakeType] | None,\n    ) -> dict[str, ColumnDef]:\n        \"\"\"Convert a record type to a dict of column name -> 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":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/snowflake/_target.py#L123-L159","documentation":"The Snowflake target's `from_class` requires `record_type` to be a structured record type (dataclass, NamedTuple, or Pydantic model) from which column definitions can be derived. Passing any other type (dict, plain class, None, etc.) fails the `is_record_type` check and raises a TypeError. This enforces that table columns can be introspected from field annotations.","triggerScenarios":"Calling `SnowflakeTableTarget.from_class(record_type=...)` (directly or via `table_target`) with a dict, a non-annotated plain class, a TypedDict, None, or any object not recognized as a dataclass/NamedTuple/Pydantic model.","commonSituations":"Passing a TypedDict (not supported), passing a dict describing columns manually, forgetting the @dataclass decorator, or using a Pydantic v1 model where only v2-style models are detected.","solutions":["Decorate the class with @dataclasses.dataclass (with type annotations on all fields) and pass that class.","Use a typing.NamedTuple subclass with annotated fields instead.","If using Pydantic, ensure it is a supported (BaseModel) class and that pydantic is installed.","Check for typos — e.g. passing an instance or the module instead of the class."],"exampleFix":"// before\nspec = {\"id\": int, \"text\": str}\ntarget = snowflake.table_target(record_type=spec, ...)\n// after\n@dataclasses.dataclass\nclass RowSpec:\n    id: int\n    text: str\n\ntarget = snowflake.table_target(record_type=RowSpec, ...)","handlingStrategy":"type-guard","validationCode":"import dataclasses, typing\nfrom pydantic import BaseModel\n\ndef is_valid_record_type(rt) -> bool:\n    return dataclasses.is_dataclass(rt) or (\n        isinstance(rt, type) and issubclass(rt, tuple) and hasattr(rt, \"_fields\")\n    ) or (isinstance(rt, type) and issubclass(rt, BaseModel))\n\nassert is_valid_record_type(RowSpec), \"record_type must be a dataclass/NamedTuple/Pydantic model\"","typeGuard":"def is_record_type(rt: object) -> TypeGuard[type]:\n    import dataclasses\n    from pydantic import BaseModel\n    return (\n        isinstance(rt, type)\n        and (dataclasses.is_dataclass(rt) or issubclass(rt, BaseModel)\n             or (issubclass(rt, tuple) and hasattr(rt, '_fields')))\n    )","tryCatchPattern":"try:\n    target = snowflake.table_target(record_type=RowSpec, ...)\nexcept TypeError as e:\n    if \"record_type must be a record type\" in str(e):\n        raise ConfigError(\"Define RowSpec as @dataclass / NamedTuple / BaseModel\") from e\n    raise","preventionTips":["Always declare record types with @dataclasses.dataclass and fully annotated fields.","Avoid TypedDict — it is not accepted as a record type here.","Unit-test target construction at import time to catch schema mistakes early."],"tags":["python","snowflake","type-validation"],"backgroundTag":"invalid-argument-value","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"}