cocoindex-io/cocoindex · error · ValueError

Primary key column {primary_key!r} must be a scalar field, g

Error message

Primary key column {primary_key!r} must be a scalar field, got kind {columns[primary_key].kind!r}.

What it means

The zvec collection target validates, at construction, that the column designated as the primary key is a scalar field, because the primary-key value is converted to a string and used as the document id. If the chosen column is a vector (dense/sparse) or other non-scalar kind, no valid document id can be derived, so a ValueError is raised in __init__.

Source

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

    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,
        ]
        | None = None,
    ) -> "CollectionSchema[RowT]":
        """Build a CollectionSchema from a record type.

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Set primary_key to a column declared with kind 'scalar' (e.g. an int/str id field).
  2. Add a scalar id column to your record type and use it as primary_key.
  3. If using from_class, ensure the dataclass/NamedTuple has a scalar field (str/int) and pass its name as primary_key.

Example fix

// before
CollectionSpec(columns={"id": Column(kind="dense", dim=768)}, primary_key="id")
// after
CollectionSpec(columns={"doc_id": Column(kind="scalar"), "embedding": Column(kind="dense", dim=768)}, primary_key="doc_id")
Defensive patterns

Strategy: validation

Validate before calling

cols = schema.columns
assert cols[schema.primary_key].kind == "scalar", "primary key must be scalar"

Type guard

def is_valid_pk(schema) -> bool:
    pk = schema.columns.get(schema.primary_key)
    return pk is not None and pk.kind == "scalar"

Prevention

When it happens

Trigger: Constructing _CollectionSpec (or declaring a zvec collection target) with primary_key set to a column whose schema kind is 'dense' or 'sparse' instead of 'scalar'.

Common situations: Pointing primary_key at a vector/embedding column by mistake; auto-generating primary_key from field inference when the dataclass only has a vector field; renaming a scalar id column to a vector column after a schema change.

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/5493947ff25c0986. Report an issue: GitHub.