cocoindex-io/cocoindex · error · ValueError

Primary key column not found in columns

Error message

Primary key column {primary_key!r} not found in columns: {list(columns.keys())}

What it means

When constructing the collection schema object (via from_class output), the designated primary_key must exist among the resolved columns and be a scalar field. __init__ raises ValueError if the primary key name is not a key in the columns dict.

Solutions

  1. Set primary_key to the exact name of an existing column
  2. Check the spelling against the declared columns list shown in the message
  3. Make sure the primary key field is a scalar (not vector/fts) column

Example fix

// before
this.collection_target(row_type=Doc, primary_key="id")  # class has field 'doc_id'
// after
this.collection_target(row_type=Doc, primary_key="doc_id")
Defensive patterns

Strategy: validation

Validate before calling

cols = {n: get_type_hints(Row, include_extras=True) for n in ...}
assert primary_key in columns, f"{primary_key!r} not in columns: {list(columns)}"

Try / catch

try:
    schema = ZvecCollection(columns, primary_key=pk)
except ValueError as e:
    if "not found in columns" in str(e):
        pk = next(iter(columns))
        schema = ZvecCollection(columns, primary_key=pk)
    else:
        raise

Prevention

When it happens

Trigger: Passing primary_key="id" when the row class has no field named 'id' (renamed field, wrong name, typo) to collection_target/from_class.

Common situations: Renaming a dataclass field without updating primary_key; assuming a default key name; programmatic schema building where the key name comes from config.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at python/cocoindex/connectors/zvec/_target.py:465

    vector fields.
    """

    columns: dict[str, _Column]
    primary_key: str
    row_type: type[RowT] | None

    def __init__(
        self,
        columns: dict[str, _Column],
        primary_key: str,
        *,
        row_type: type[RowT] | None = None,
    ) -> None:
        self.columns = columns
        self.primary_key = primary_key
        self.row_type = row_type
        if primary_key not in columns:
            raise ValueError(
                f"Primary key column {primary_key!r} not found in columns: "
                f"{list(columns.keys())}"
            )
        if columns[primary_key].kind != "scalar":
            raise ValueError(
                f"Primary key column {primary_key!r} must be a scalar field, "
                f"got kind {columns[primary_key].kind!r}."
            )

    @classmethod
    async def from_class(
        cls,
        record_type: type[RowT],
        primary_key: list[str],
        *,
        column_overrides: dict[
            str,
            ZvecType | ZvecVectorDef | ZvecFtsType | res_schema.VectorSchemaProvider,

View on GitHub (pinned to e84aa99b32)