{"record":{"id":"2550edec367fb04a","repo":"mem0ai/mem0","slug":"invalid-filter-key-key-r-2550ed","errorCode":null,"errorMessage":"Invalid filter key: {key!r}","messagePattern":"Invalid filter key: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mem0/vector_stores/neptune_analytics.py","lineNumber":24,"sourceCode":"\nfrom pydantic import BaseModel\n\ntry:\n    from langchain_aws import NeptuneAnalyticsGraph\nexcept ImportError:\n    raise ImportError(\"langchain_aws is not installed. Please install it using pip install langchain_aws\")\n\nfrom mem0.vector_stores.base import VectorStoreBase\n\nlogger = logging.getLogger(__name__)\n\n_SAFE_FILTER_KEY = re.compile(r\"^[a-zA-Z_~][a-zA-Z0-9_]*$\")\n_VALID_IDENTIFIER = re.compile(r\"^[A-Za-z_][A-Za-z0-9_]*$\")\n\n\ndef _validate_filter(key: str, value: Any) -> None:\n    if not isinstance(key, str) or not _SAFE_FILTER_KEY.match(key):\n        raise ValueError(f\"Invalid filter key: {key!r}\")\n    if not isinstance(value, (str, int, float, bool)):\n        raise ValueError(\n            f\"Filter value for {key!r} must be str, int, float, or bool, \"\n            f\"got {type(value).__name__}\"\n        )\n\n\ndef _escape_cypher(value: str) -> str:\n    return value.replace(\"\\\\\", \"\\\\\\\\\").replace(\"'\", \"\\\\'\")\n\nclass OutputData(BaseModel):\n    id: Optional[str]  # memory id\n    score: Optional[float]  # distance\n    payload: Optional[Dict]  # metadata\n\n\nclass NeptuneAnalyticsVector(VectorStoreBase):\n    \"\"\"","sourceCodeStart":6,"sourceCodeEnd":42,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0/vector_stores/neptune_analytics.py#L6-L42","documentation":"Neptune Analytics builds openCypher queries from your filters, so filter keys are validated against ^[a-zA-Z_~][a-zA-Z0-9_]*$. This error means a key failed that pattern: it is either not a string or contains characters (spaces, dots, dashes, $, unicode) that cannot appear safely as a property key in the generated Cypher.","triggerScenarios":"Passing filters={\"user-id\": \"u1\"} (dash), {\"user id\": \"u1\"} (space), {\"app.version\": 2} (dot), or a non-string key (int from JSON with numeric keys) to search/list on the Neptune Analytics backend.","commonSituations":"Reusing filters written for the Qdrant/OpenSearch backends (which allow dots) against Neptune; forwarding raw HTTP query params as filter keys; camelCase keys with exotic separators from analytics pipelines.","solutions":["Rename filter keys to letters, digits, underscore, with an optional leading tilde (e.g. \"user_id\", \"app_version\")","Normalize/whitelist filter keys at your API boundary before they reach Mem0","Store the exotic key inside the payload and filter on a sanitized alias key instead"],"exampleFix":"// before\nfilters = {\"user-id\": \"alice\", \"app.version\": \"v2\"}\n\n// after\nfilters = {\"user_id\": \"alice\", \"app_version\": \"v2\"}","handlingStrategy":"validation","validationCode":"import re\nSAFE_KEY = re.compile(r\"^[a-zA-Z_~][a-zA-Z0-9_]*$\")\n\ndef sanitize_neptune_keys(filters: dict) -> dict:\n    return {re.sub(r\"[^a-zA-Z0-9_]\", \"_\", k): v for k, v in (filters or {}).items()\n            if isinstance(k, str)}\n\nfilters = sanitize_neptune_keys(filters)","typeGuard":"def is_neptune_safe_key(k) -> bool:\n    return isinstance(k, str) and bool(re.match(r\"^[a-zA-Z_~][a-zA-Z0-9_]*$\", k))","tryCatchPattern":"try:\n    store.search(q, vec, filters=filters)\nexcept ValueError as e:\n    if \"Invalid filter key\" in str(e):\n        filters = sanitize_neptune_keys(filters)\n        store.search(q, vec, filters=filters)\n    else:\n        raise","preventionTips":["Standardize on snake_case filter keys project-wide","Do not reuse backend-specific filter dicts across providers","Whitelist filter keys coming from HTTP parameters"],"tags":["neptune","aws","cypher-injection","security","filters","validation"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}