{"record":{"id":"f4656e2e0e7e1f2e","repo":"mem0ai/mem0","slug":"invalid-filter-key-key-r-f4656e","errorCode":null,"errorMessage":"Invalid filter key: {key!r}","messagePattern":"Invalid filter key: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mem0/vector_stores/elasticsearch.py","lineNumber":30,"sourceCode":"\nfrom mem0.configs.vector_stores.elasticsearch import ElasticsearchConfig\nfrom mem0.vector_stores.base import VectorStoreBase\n\nlogger = logging.getLogger(__name__)\n\n\nclass OutputData(BaseModel):\n    id: str\n    score: float\n    payload: Dict\n\n\n_SAFE_FILTER_KEY = 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\nclass ElasticsearchDB(VectorStoreBase):\n    def __init__(self, **kwargs):\n        config = ElasticsearchConfig(**kwargs)\n\n        # Initialize Elasticsearch client\n        if config.cloud_id:\n            self.client = Elasticsearch(\n                cloud_id=config.cloud_id,\n                api_key=config.api_key,\n                verify_certs=config.verify_certs,\n                ca_certs=config.ca_certs,","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0/vector_stores/elasticsearch.py#L12-L48","documentation":"ValueError from _validate_filter in elasticsearch.py: filter keys must be strings matching ^[a-zA-Z_][a-zA-Z0-9_]*$ before being embedded into the ES query DSL. Keys with dots, hyphens, spaces, leading digits, or non-str key types (int keys from JSON like {0: 'x'}) are rejected to keep the generated ES queries well-formed and injection-safe.","triggerScenarios":"Calling search/get on ElasticsearchDB with filters={'user-id': ...}, {'metadata.role': ...}, {123: 'v'}, or {'': 'x'}. Validation runs for each key/value pair before the ES query is built.","commonSituations":"Reusing filter dicts written for providers that allow dotted paths; keys sourced from arbitrary user/JSON payloads; numeric dict keys after JSON round-tripping.","solutions":["Use plain identifier keys: letters/digits/underscore, first char not a digit.","Sanitize at the boundary: key = re.sub(r'[^A-Za-z0-9_]', '_', str(key)) or drop invalid keys with a warning.","Keep a whitelist of allowed filter keys per feature and validate input against it."],"exampleFix":"# before\ndb.search(query, vectors, filters={\"user-id\": \"alice\"})  # ValueError\n\n# after\ndb.search(query, vectors, filters={\"user_id\": \"alice\"})","handlingStrategy":"validation","validationCode":"import re\n_SAFE_KEY = re.compile(r\"^[a-zA-Z_][a-zA-Z0-9_]*$\")\n\ndef clean_es_filters(filters: dict) -> dict:\n    return {k: v for k, v in (filters or {}).items() if isinstance(k, str) and _SAFE_KEY.match(k)}\n\ndb.search(query, vectors, filters=clean_es_filters(filters))","typeGuard":"def has_safe_es_filter_keys(filters: dict) -> bool:\n    import re\n    return all(isinstance(k, str) and re.match(r\"^[a-zA-Z_][a-zA-Z0-9_]*$\", k) for k in (filters or {}))","tryCatchPattern":null,"preventionTips":["Store metadata under identifier-safe keys from the start.","Do not translate ES DSL ('term'/'range' objects) into provider filters; use scalar equality only.","Share one filter sanitizer across all vector store providers in your codebase."],"tags":["elasticsearch","filters","validation","injection-guard"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}