cocoindex-io/cocoindex · error · ValueError

Primary key column ' ' not found in columns

Error message

Primary key column '{pk}' not found in columns: {list(self.columns.keys())}

What it means

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.

Solutions

  1. Fix primary_key names to match the column names exactly.
  2. If using from_class, ensure the primary key names match dataclass field names.
  3. Add a missing field/column if it was unintentionally dropped.

Example fix

// before
PgTableTarget.from_class(UserRow, primary_key=["uid"])
// after
PgTableTarget.from_class(UserRow, primary_key=["id"])  # matches field name
Defensive patterns

Strategy: validation

Validate before calling

import dataclasses
fields = {f.name for f in dataclasses.fields(UserRow)}
assert set(primary_key) <= fields, f"PK columns missing: {set(primary_key) - fields}"

Type guard

def primary_key_valid(row_type: type, primary_key: list[str]) -> bool:
    names = {f.name for f in dataclasses.fields(row_type)}
    return set(primary_key) <= names

Try / catch

try:
    target = await PgTableTarget.from_class(Row, primary_key=pk)
except ValueError as e:
    if "not found in columns" in str(e):
        raise ValueError(f"Fix primary_key; available: {list(get_column_names(Row))}") from e

Prevention

When it happens

Trigger: 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.

Common situations: Renaming dataclass fields without updating primary_key; typos in primary key names; sharing a primary_key list between tables with different schemas.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/ffad8f778d67c98c. Report an issue: GitHub.

Appendix: source

Thrown at python/cocoindex/connectors/postgres/_target.py:359

        """
        Create a TableSchema from pre-resolved column definitions.

        For constructing from a record type, use the async classmethod
        ``from_class`` instead.

        Args:
            columns: A dict mapping column names to ColumnDef.
            primary_key: List of column names that form the primary key.
            row_type: Optional original record type.
        """
        self.columns = columns
        self.primary_key = primary_key
        self.row_type = row_type

        # Validate primary key columns exist
        for pk in self.primary_key:
            if pk not in self.columns:
                raise ValueError(
                    f"Primary key column '{pk}' not found in columns: {list(self.columns.keys())}"
                )

    @classmethod
    async def from_class(
        cls,
        record_type: type[RowT],
        primary_key: list[str],
        *,
        column_overrides: dict[str, PgType | res_schema.VectorSchemaProvider]
        | None = None,
    ) -> "TableSchema[RowT]":
        """
        Create a TableSchema from a record type (dataclass, NamedTuple, or Pydantic model).

        Python types are automatically mapped to PostgreSQL types based on asyncpg's
        type conversion.

View on GitHub (pinned to e84aa99b32)