{"record":{"id":"938edfe18618f2f1","repo":"cocoindex-io/cocoindex","slug":"invalid-surrealdb-kind-name-r-must-match-a","errorCode":null,"errorMessage":"Invalid SurrealDB {kind}: {name!r}. Must match [a-zA-Z_][a-zA-Z0-9_]*.","messagePattern":"Invalid SurrealDB (.+?): (.+?)\\. Must match \\[a-zA-Z_\\]\\[a-zA-Z0-9_\\]\\*\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/surrealdb/_target.py","lineNumber":81,"sourceCode":"\nfrom cocoindex.resources import schema as res_schema\nfrom cocoindex._internal.context_keys import ContextKey, ContextProvider\n\n# ---------------------------------------------------------------------------\n# Identifier validation & record ID formatting\n# ---------------------------------------------------------------------------\n\n_IDENTIFIER_RE = re.compile(r\"^[a-zA-Z_][a-zA-Z0-9_]*$\")\n\n\ndef _validate_identifier(name: str, kind: str) -> None:\n    \"\"\"Validate that *name* is a safe SurrealQL identifier.\n\n    Raises :class:`ValueError` if the name contains characters that are not\n    alphanumeric or underscore, or starts with a digit.\n    \"\"\"\n    if not _IDENTIFIER_RE.match(name):\n        raise ValueError(\n            f\"Invalid SurrealDB {kind}: {name!r}. Must match [a-zA-Z_][a-zA-Z0-9_]*.\"\n        )\n\n\ndef _format_record_id(value: Any) -> str:\n    \"\"\"Format a record ID for inline use in SurrealQL, preserving type.\n\n    * ``int`` / ``float`` → bare numeric literal (``123``, ``3.14``)\n    * ``str`` (and everything else) → backtick-quoted with ``\\\\`` and\n      backtick escaping (`` `alice` ``, `` `has\\\\`tick` ``)\n    \"\"\"\n    if isinstance(value, (int, float)):\n        return str(value)\n    s = str(value)\n    s = s.replace(\"\\\\\", \"\\\\\\\\\").replace(\"`\", \"\\\\`\")\n    return f\"`{s}`\"\n\n","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/surrealdb/_target.py#L63-L99","documentation":"SurrealQL identifiers (table names, index names, column names) used inline in generated SurrealQL must be safe: start with a letter or underscore and contain only alphanumerics/underscores. CocoIndex validates all such names up front (in __init__, declare_vector_index, table_target, relation_target) to prevent syntax errors and injection via crafted names.","triggerScenarios":"Creating a relation_target/table_target or declaring a vector index with a name containing hyphens, dots, spaces, digits at position 0, or other non-identifier characters, e.g. table name 'my-table' or an index named 'idx.embedding'.","commonSituations":"Deriving table names from file paths or user input ('docs-2024'); using dotted or dashed names common in other databases; generating names programmatically without sanitizing.","solutions":["Rename to a valid identifier: letters/underscore first, then alphanumerics/underscores only (e.g. 'my_table').","Sanitize derived names programmatically before passing them (replace invalid chars with '_').","Quote/escape is not offered by this API surface, so renaming is the only path."],"exampleFix":"// before\nrelation_target(name=\"my-table\", ...)\n// after\nrelation_target(name=\"my_table\", ...)","handlingStrategy":"validation","validationCode":"import re\n_IDENT = re.compile(r\"[a-zA-Z_][a-zA-Z0-9_]*$\")\ndef assert_valid_name(name: str) -> None:\n    if not _IDENT.match(name):\n        raise ValueError(f\"invalid SurrealDB identifier: {name!r}\")","typeGuard":"def is_safe_identifier(name: str) -> bool:\n    import re\n    return bool(re.fullmatch(r\"[a-zA-Z_][a-zA-Z0-9_]*\", name))","tryCatchPattern":"try:\n    target = relation_target(name=user_supplied_name, ...)\nexcept ValueError as e:\n    if \"Invalid SurrealDB\" in str(e):\n        name = re.sub(r\"\\W\", \"_\", user_supplied_name)\n        target = relation_target(name=name, ...)","preventionTips":["Sanitize names derived from file paths or user input before creating targets.","Enforce snake_case naming conventions for tables and indexes.","Validate names in a shared helper instead of passing raw strings around."],"tags":["surrealdb","identifier","validation","naming"],"backgroundTag":"invalid-identifier-format","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}