{"record":{"id":"ffad8f778d67c98c","repo":"cocoindex-io/cocoindex","slug":"primary-key-column-pk-not-found-in-columns-l-ffad8f","errorCode":null,"errorMessage":"Primary key column '{pk}' not found in columns: {list(self.columns.keys())}","messagePattern":"Primary key column '(.+?)' not found in columns: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/postgres/_target.py","lineNumber":359,"sourceCode":"        \"\"\"\n        Create a TableSchema from pre-resolved column definitions.\n\n        For constructing from a record type, use the async classmethod\n        ``from_class`` instead.\n\n        Args:\n            columns: A dict mapping column names to ColumnDef.\n            primary_key: List of column names that form the primary key.\n            row_type: Optional original record type.\n        \"\"\"\n        self.columns = columns\n        self.primary_key = primary_key\n        self.row_type = row_type\n\n        # Validate primary key columns exist\n        for pk in self.primary_key:\n            if pk not in self.columns:\n                raise ValueError(\n                    f\"Primary key column '{pk}' not found in columns: {list(self.columns.keys())}\"\n                )\n\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, PgType | res_schema.VectorSchemaProvider]\n        | None = None,\n    ) -> \"TableSchema[RowT]\":\n        \"\"\"\n        Create a TableSchema from a record type (dataclass, NamedTuple, or Pydantic model).\n\n        Python types are automatically mapped to PostgreSQL types based on asyncpg's\n        type conversion.\n","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/postgres/_target.py#L341-L377","documentation":"Every column named in primary_key must exist among the table's declared columns; the primary key is emitted in SQL constraints against these columns. A missing name means the table definition is inconsistent, so __init__ raises ValueError.","triggerScenarios":"Constructing PgTableTarget(columns=..., primary_key=['id']) where 'id' is not a key of the columns dict, e.g. after renaming a column or passing a raw column list from a different record type.","commonSituations":"Renaming dataclass fields without updating primary_key; typos in primary key names; sharing a primary_key list between tables with different schemas.","solutions":["Fix primary_key names to match the column names exactly.","If using from_class, ensure the primary key names match dataclass field names.","Add a missing field/column if it was unintentionally dropped."],"exampleFix":"// before\nPgTableTarget.from_class(UserRow, primary_key=[\"uid\"])\n// after\nPgTableTarget.from_class(UserRow, primary_key=[\"id\"])  # matches field name","handlingStrategy":"validation","validationCode":"import dataclasses\nfields = {f.name for f in dataclasses.fields(UserRow)}\nassert set(primary_key) <= fields, f\"PK columns missing: {set(primary_key) - fields}\"","typeGuard":"def primary_key_valid(row_type: type, primary_key: list[str]) -> bool:\n    names = {f.name for f in dataclasses.fields(row_type)}\n    return set(primary_key) <= names","tryCatchPattern":"try:\n    target = await PgTableTarget.from_class(Row, primary_key=pk)\nexcept ValueError as e:\n    if \"not found in columns\" in str(e):\n        raise ValueError(f\"Fix primary_key; available: {list(get_column_names(Row))}\") from e","preventionTips":["Keep primary_key lists in the same module as the row dataclass.","Rename fields and primary keys in the same commit.","Add a test asserting every pk name is a dataclass field."],"tags":["python","sql","schema","validation"],"backgroundTag":"schema-validation-failed","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"}