cocoindex-io/cocoindex · error

Invalid FalkorDB {kind}: {name!r}. Must match [a-zA-Z_][a-zA

Error message

Invalid FalkorDB {kind}: {name!r}. Must match [a-zA-Z_][a-zA-Z0-9_]*.

What it means

validate_identifier() rejects names used as Cypher labels, relationship types, or property names that don't match [a-zA-Z_][a-zA-Z0-9_]*. Cypher identifiers cannot be parameter-bound, so this library inlines them into query text; to prevent Cypher injection and syntax errors, untrusted names are validated at API entry instead of escaped at query construction time.

Source

Thrown at python/cocoindex/connectors/falkordb/_cypher.py:44

    "build_relationship_index_drop",
    "build_vector_index_create",
    "build_vector_index_drop",
    "validate_identifier",
]


IDENTIFIER_RE = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")


def validate_identifier(name: str, kind: str) -> None:
    """Reject anything that isn't ``[a-zA-Z_][a-zA-Z0-9_]*``.

    Cypher labels and property names cannot be parameter-bound, so untrusted
    names must be validated at API entry — never escaped at query construction
    time.
    """
    if not IDENTIFIER_RE.match(name):
        raise ValueError(
            f"Invalid FalkorDB {kind}: {name!r}. Must match [a-zA-Z_][a-zA-Z0-9_]*."
        )


def _quote(name: str) -> str:
    """Backtick-wrap an already-validated identifier for inline use in Cypher."""
    return f"`{name}`"


def _key_clause(prefix: str, fields: Sequence[str], var: str) -> str:
    """Build ``{<f1>: $<prefix>_0, <f2>: $<prefix>_1, ...}`` for a MATCH/MERGE pattern.

    ``var`` is unused here but accepted so callers can self-document intent
    (e.g. ``var="n"`` makes it clear this clause attaches to ``n``).
    """
    parts = [f"{_quote(f)}: ${prefix}_{i}" for i, f in enumerate(fields)]
    return "{" + ", ".join(parts) + "}"

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Sanitize the name before passing it: strip/replace invalid characters so it matches [a-zA-Z_][a-zA-Z0-9_]*.
  2. Verify the name is non-empty and starts with a letter or underscore, not a digit.
  3. If the name must contain special characters, map it to a safe alias and store the mapping in a property instead of the identifier.

Example fix

// before
label = file.path.parent.name  # e.g. '2024-01'
await target.declare_node(label=label, ...)
// after
import re
safe = re.sub(r'\W', '_', file.path.parent.name)
if not re.match(r'[a-zA-Z_]', safe):
    safe = '_' + safe
await target.declare_node(label=safe, ...)
Defensive patterns

Strategy: validation

Validate before calling

import re
_IDENT = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*')

def check_identifier(name: str, kind: str = 'identifier') -> str:
    if not _IDENT.match(name):
        raise ValueError(f'{kind} {name!r} must match [a-zA-Z_][a-zA-Z0-9_]*')
    return name

# before calling any falkordb API:
label = check_identifier(raw_label, 'label')

Type guard

def is_valid_identifier(name: object) -> bool:
    return isinstance(name, str) and bool(re.fullmatch(r'[a-zA-Z_][a-zA-Z0-9_]*', name))

Prevention

When it happens

Trigger: Calling any falkordb connector API with a label, rel type, or property/field name containing characters outside [a-zA-Z_][a-zA-Z0-9_]* — e.g. leading digit ('2024_events'), hyphens ('my-label'), dots, spaces, or empty string ''.

Common situations: Deriving graph labels from file paths, table names, or user input that wasn't sanitized (e.g. turning 'logs/2024-01' into a label); auto-generating labels from data source names with dashes; localization or prefixed names like '$events'.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


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