cocoindex-io/cocoindex · error · ValueError

build_constraint_create requires at least one field

Error message

build_constraint_create requires at least one field

What it means

This ValueError is raised by build_constraint_create when the fields sequence for a Neo4j node constraint (UNIQUE for single field, NODE KEY for compound) is empty. A constraint must reference at least one property; generating the REQUIRE clause with no fields would be invalid Cypher. The library validates before building the statement.

Source

Thrown at python/cocoindex/connectors/neo4j/_cypher.py:224

    """``DROP INDEX <name> IF EXISTS``.

    Same DROP statement as for node indexes — Neo4j unifies the namespace.
    """
    return f"DROP INDEX {_quote(name)} IF EXISTS"


def build_constraint_create(
    name: str,
    label: str,
    fields: Sequence[str],
) -> str:
    """``CREATE CONSTRAINT <name> IF NOT EXISTS FOR (n:`Label`) REQUIRE n.`f1` IS UNIQUE``.

    For a single-field PK uses ``REQUIRE n.f IS UNIQUE``; for compound PKs
    uses ``REQUIRE (n.f1, n.f2) IS NODE KEY`` (Neo4j 5 syntax).
    """
    if not fields:
        raise ValueError("build_constraint_create requires at least one field")
    if len(fields) == 1:
        field_expr = f"n.{_quote(fields[0])} IS UNIQUE"
    else:
        field_list = ", ".join(f"n.{_quote(f)}" for f in fields)
        field_expr = f"({field_list}) IS NODE KEY"
    return (
        f"CREATE CONSTRAINT {_quote(name)} IF NOT EXISTS "
        f"FOR (n:{_quote(label)}) REQUIRE {field_expr}"
    )


def build_constraint_drop(name: str) -> str:
    """``DROP CONSTRAINT <name> IF EXISTS``."""
    return f"DROP CONSTRAINT {_quote(name)} IF EXISTS"


def build_vector_index_create(
    name: str,

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Pass at least one field name, e.g. ['id'] for a UNIQUE constraint or ['org_id','user_id'] for a NODE KEY.
  2. Guard the call site: skip constraint creation if the fields list is empty.
  3. Check where fields is constructed to ensure the schema's key columns are captured.

Example fix

// before
build_constraint_create("user_email_unique", "User", [])
// after
build_constraint_create("user_email_unique", "User", ["email"])
Defensive patterns

Strategy: validation

Validate before calling

if not fields:
    raise ValueError("constraint fields must contain at least one property")
build_constraint_create(name, label, fields)

Try / catch

try:
    stmt = build_constraint_create(name, label, fields)
except ValueError as e:
    logging.warning("skipping constraint %s: %s", name, e)

Prevention

When it happens

Trigger: Calling build_constraint_create(name, label, fields=[]) — e.g. passing an empty primary-key field list from config or schema introspection.

Common situations: A table/node schema whose primary key fields list is empty; a typo causing the fields list to be filtered down to nothing; wiring up constraint creation before the schema is populated.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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