{"record":{"id":"293ebf1869c0813d","repo":"cocoindex-io/cocoindex","slug":"build-node-upsert-requires-at-least-one-primary-ke","errorCode":null,"errorMessage":"build_node_upsert requires at least one primary key field","messagePattern":"build_node_upsert requires at least one primary key field","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/falkordb/_cypher.py","lineNumber":76,"sourceCode":"    (e.g. ``var=\"n\"`` makes it clear this clause attaches to ``n``).\n    \"\"\"\n    parts = [f\"{_quote(f)}: ${prefix}_{i}\" for i, f in enumerate(fields)]\n    return \"{\" + \", \".join(parts) + \"}\"\n\n\ndef build_node_upsert(\n    label: str,\n    pk_fields: Sequence[str],\n    has_value_fields: bool,\n) -> str:\n    \"\"\"``MERGE (n:`Label` {pk: $key_0, ...}) [SET n += $props]``.\n\n    ``has_value_fields`` controls whether the ``SET n += $props`` clause is\n    emitted. Caller passes ``True`` when there is at least one non-PK column to\n    write; otherwise the MERGE alone suffices.\n    \"\"\"\n    if not pk_fields:\n        raise ValueError(\"build_node_upsert requires at least one primary key field\")\n    cypher = f\"MERGE (n:{_quote(label)} {_key_clause('key', pk_fields, 'n')})\"\n    if has_value_fields:\n        cypher += \" SET n += $props\"\n    return cypher\n\n\ndef build_node_delete(label: str, pk_fields: Sequence[str]) -> str:\n    \"\"\"``MATCH (n:`Label` {pk: $key_0, ...}) DETACH DELETE n``.\n\n    DETACH DELETE removes any incident edges as a safety measure for nodes that\n    are also referenced as relationship endpoints — without it, the DELETE\n    would fail on nodes that still have edges.\n    \"\"\"\n    if not pk_fields:\n        raise ValueError(\"build_node_delete requires at least one primary key field\")\n    return (\n        f\"MATCH (n:{_quote(label)} {_key_clause('key', pk_fields, 'n')}) \"\n        f\"DETACH DELETE n\"","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/falkordb/_cypher.py#L58-L94","documentation":"build_node_upsert() refuses to build a MERGE query when pk_fields is empty. A MERGE needs at least one key property to identify the node uniquely; without primary key fields the upsert would match every node or be meaningless, so the library fails fast instead of generating a broken Cypher query.","triggerScenarios":"Calling build_node_upsert(label, pk_fields=[], ...) — i.e. declaring a node table/handler with no primary key fields configured.","commonSituations":"Schema definition omitted the primary key (e.g. forgot to mark 'id' as a key column); a table maps only non-key value columns; a key fields list was built programmatically and filtered to empty.","solutions":["Declare at least one primary key field in the node table schema (e.g. the unique 'id' column) and pass it in pk_fields.","Check the code that builds the pk_fields list — a filter or optional config may be dropping the key fields.","If the node truly has no natural key, designate a deterministic unique property (e.g. content hash) as the primary key."],"exampleFix":"// before\nbuild_node_upsert(label=\"Person\", pk_fields=[], value_fields=[\"name\"])\n// after\nbuild_node_upsert(label=\"Person\", pk_fields=[\"person_id\"], value_fields=[\"name\"])","handlingStrategy":"validation","validationCode":"if not pk_fields:\n    raise ValueError('node table needs at least one primary key field before upsert')\n# proceed with build_node_upsert(label, pk_fields, ...)","typeGuard":"def has_pk_fields(pk_fields: object) -> bool:\n    return isinstance(pk_fields, (list, tuple)) and len(pk_fields) > 0","tryCatchPattern":"try:\n    cypher = build_node_upsert(label, pk_fields, has_value_fields)\nexcept ValueError as e:\n    logger.error('node upsert misconfigured: %s', e)\n    raise ConfigError(f'table {label!r} must declare a primary key field') from e","preventionTips":["Always designate exactly one unique key column in every node table schema.","When building pk_fields programmatically, assert non-empty before calling the builder.","Use a deterministic key (e.g. content hash) for data without a natural unique id."],"tags":["cypher","falkordb","primary-key","schema"],"backgroundTag":"missing-required-argument","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}