{"record":{"id":"f31e5cc27fb97f07","repo":"cocoindex-io/cocoindex","slug":"cannot-specify-both-row-factory-and-row-type","errorCode":null,"errorMessage":"Cannot specify both row_factory and row_type","messagePattern":"Cannot specify both row_factory and row_type","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/postgres/_source.py","lineNumber":205,"sourceCode":"        table_name: str,\n        columns: Sequence[str] | None = ...,\n        pg_schema_name: str | None = ...,\n        row_factory: None = ...,\n        row_type: type[RowT],\n    ) -> None: ...\n\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(","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/postgres/_source.py#L187-L223","documentation":"PostgresSource row customization accepts either a row_factory callable or a row_type record class, but not both, since each fully determines how rows are built and which columns are resolved. Specifying both is ambiguous, so __init__ raises ValueError immediately.","triggerScenarios":"Calling PostgresSource(...) with both a non-None row_factory and a non-None row_type argument, e.g. PostgresSource(table='t', row_factory=my_fn, row_type=MyRecord).","commonSituations":"Developers migrating from a factory function to a typed record leave the old row_factory kwarg in place while adding row_type for type hints; copying example code that sets one option without noticing the other.","solutions":["Remove either the row_factory or the row_type argument so only one is passed.","If you need custom row construction, keep row_factory and drop row_type.","If you want typed records (dataclass/NamedTuple/Pydantic), keep row_type and delete row_factory."],"exampleFix":"// before\nsrc = PostgresSource(table=\"users\", row_factory=build_user, row_type=User)\n// after\nsrc = PostgresSource(table=\"users\", row_type=User)","handlingStrategy":"validation","validationCode":"assert not (row_factory is not None and row_type is not None), \"Pass only one of row_factory or row_type\"","typeGuard":"def has_conflict(kwargs: dict) -> bool:\n    return kwargs.get(\"row_factory\") is not None and kwargs.get(\"row_type\") is not None","tryCatchPattern":"try:\n    src = PostgresSource(table=\"t\", row_factory=f, row_type=R)\nexcept ValueError as e:\n    if \"both row_factory and row_type\" in str(e):\n        src = PostgresSource(table=\"t\", row_type=R)","preventionTips":["Pick one row-mapping style per source and standardize on it (prefer row_type).","Wrap source construction in a helper function that enforces the exclusivity.","Enable keyword-argument linting/review when copying example snippets."],"tags":["python","configuration","validation"],"backgroundTag":"mutually-exclusive-options","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"}