cocoindex-io/cocoindex · error
row is missing primary key field {self._primary_key!r}
Error message
row is missing primary key field {self._primary_key!r} What it means
`TableTarget.declare_record` converts the row to a dict and requires the schema's primary key field to be present so it can compute the target-state key. A row lacking that field (after `_row_to_dict`) cannot be keyed/upserted, so ValueError is raised naming the missing field.
Source
Thrown at python/cocoindex/connectors/falkordb/_target.py:1273
) -> None:
self._provider = provider
self._table_schema = table_schema
self._table_name = table_name
self._primary_key = primary_key
@property
def table_name(self) -> str:
return self._table_name
@property
def primary_key(self) -> str:
return self._primary_key
def declare_record(self: TableTarget[RowT], *, row: RowT) -> None:
"""Declare a record (node) to be upserted to this table."""
row_dict = self._row_to_dict(row)
if self._primary_key not in row_dict:
raise ValueError(f"row is missing primary key field {self._primary_key!r}")
pk_values = (row_dict[self._primary_key],)
coco.declare_target_state(self._provider.target_state(pk_values, row_dict))
declare_row = declare_record
def _row_to_dict(self, row: RowT) -> dict[str, Any]:
if self._table_schema is not None:
out: dict[str, Any] = {}
for col_name, col in self._table_schema.columns.items():
if isinstance(row, dict):
value = row.get(col_name)
else:
value = getattr(row, col_name)
if value is not None and col.encoder is not None:
value = col.encoder(value)
out[col_name] = value
return out
if isinstance(row, dict):View on GitHub (pinned to e84aa99b32)
Solutions
- Ensure every row passed to `declare_record` includes the primary key field with a non-None value.
- Align the row class/annotation with the schema's `row_type` so `_row_to_dict` yields the key.
- If the key is derived, compute it explicitly before declaring, e.g. `row = Person(id=slug(name), ...)`.
Example fix
// before target.declare_record(row=Person(name="Alice")) # schema primary_key="id" // after target.declare_record(row=Person(id="alice", name="Alice"))
Defensive patterns
Strategy: validation
Validate before calling
row_dict = dataclasses.asdict(row)
assert schema.primary_key in row_dict and row_dict[schema.primary_key] is not None, \
f"row missing primary key {schema.primary_key!r}"
target.declare_record(row=row) Type guard
def has_pk(row: object, pk: str) -> bool:
return getattr(row, pk, None) is not None Try / catch
try:
target.declare_record(row=row)
except ValueError as e:
if "missing primary key field" in str(e):
logging.error("Row %r lacks key field; regenerate rows with id set: %s", row, e)
raise Prevention
- Make the primary key a required field in the row dataclass (no default).
- Construct rows through a factory that always fills the key.
- Type row parameters as the schema's RowT so field drift is caught by mypy.
When it happens
Trigger: Calling `target.declare_record(row=...)` (or `declare_row`) with a row object whose dict form lacks the primary key field — e.g. a dataclass missing the `id` field, or a plain object whose attribute name differs from the schema key.
Common situations: Row type drifted from the schema (field renamed); constructing rows ad-hoc in a graph-building function (see callers like `build_graph`, `sync_person_graph`) and forgetting the `id`; a custom row object not matching the declared `row_type`.
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
- primary_key {primary_key!r} not found in columns ({sorted(co
- primary_key {primary_key!r} does not match the schema's decl
- primary_key {primary_key!r} does not match schema's {table_s
- Primary key column '{pk}' not found in columns: {list(self.c
- build_node_upsert requires at least one primary key field
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/228b1b716fe8b145.
Report an issue: GitHub.