{"record":{"id":"499ce58b9fa11e4f","repo":"cocoindex-io/cocoindex","slug":"row-type-must-be-a-record-type-dataclass-namedtu","errorCode":null,"errorMessage":"row_type must be a record type (dataclass, NamedTuple, or Pydantic model), got {row_type}","messagePattern":"row_type must be a record type \\(dataclass, NamedTuple, or Pydantic model\\), got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/postgres/_source.py","lineNumber":211,"sourceCode":"\n    def __init__(\n        self,\n        pool: asyncpg.Pool,\n        *,\n        table_name: str,\n        columns: Sequence[str] | None = None,\n        pg_schema_name: str | None = None,\n        row_factory: Callable[[dict[str, Any]], RowT] | None = None,\n        row_type: type[RowT] | None = None,\n    ) -> None:\n        if row_factory is not None and row_type is not None:\n            raise ValueError(\"Cannot specify both row_factory and row_type\")\n\n        # Determine columns based on row_type\n        resolved_columns: Sequence[str] | None = columns\n        if row_type is not None:\n            if not is_record_type(row_type):\n                raise TypeError(\n                    f\"row_type must be a record type (dataclass, NamedTuple, or Pydantic model), \"\n                    f\"got {row_type}\"\n                )\n            record_info = RecordType(row_type)\n            field_names = [f.name for f in record_info.fields]\n            field_set = frozenset(field_names)\n\n            if columns is not None:\n                # Validate that all specified columns exist in the record type\n                invalid_cols = [c for c in columns if c not in field_set]\n                if invalid_cols:\n                    raise ValueError(\n                        f\"Columns {invalid_cols} not found in row_type fields: {field_names}\"\n                    )\n            else:\n                # Use record type fields as columns\n                resolved_columns = field_names\n","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/postgres/_source.py#L193-L229","documentation":"When row_type is given, it must be a supported record type — a dataclass, NamedTuple, or Pydantic model — because the connector introspects its fields to derive columns. Passing any other type raises TypeError.","triggerScenarios":"Passing row_type that is a plain class, dict, TypedDict, generic list, or an instance instead of the class itself to PostgresSource.__init__.","commonSituations":"Passing a TypedDict (not introspectable as a record here), forgetting to apply @dataclass, or accidentally passing an instance (User(...)) rather than the class.","solutions":["Decorate the class with @dataclass, base it on NamedTuple, or make it a Pydantic BaseModel.","Pass the class itself, not an instance.","If fully custom construction is needed, use row_factory instead of row_type."],"exampleFix":"// before\nsrc = PostgresSource(table=\"users\", row_type=dict)\n// after\n@dataclass\nclass User:\n    id: int\n    name: str\nsrc = PostgresSource(table=\"users\", row_type=User)","handlingStrategy":"type-guard","validationCode":"import dataclasses, typing\nassert dataclasses.is_dataclass(MyRow) or issubclass(MyRow, tuple) or hasattr(MyRow, \"model_fields\")","typeGuard":"def is_record_type(t: object) -> bool:\n    import dataclasses\n    return (\n        isinstance(t, type)\n        and (dataclasses.is_dataclass(t)\n             or issubclass(t, tuple) and hasattr(t, \"_fields\")\n             or hasattr(t, \"model_fields\"))\n    )","tryCatchPattern":"try:\n    src = PostgresSource(table=\"t\", row_type=R)\nexcept TypeError as e:\n    if \"must be a record type\" in str(e):\n        R = make_dataclass_from(R)","preventionTips":["Always decorate row classes with @dataclass or inherit NamedTuple/BaseModel.","Pass classes, never instances, as row_type.","Avoid TypedDict for row_type; it is not accepted here."],"tags":["python","type-error","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-17T15:17:12.973Z"}