{"record":{"id":"1c464efcd6c7cd77","repo":"run-llama/llama_index","slug":"nested-metadatafilters-are-not-supported","errorCode":null,"errorMessage":"Nested MetadataFilters are not supported.","messagePattern":"Nested MetadataFilters are not supported\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/vector_stores/utils.py","lineNumber":164,"sourceCode":"                if isinstance(value, str) and isinstance(metadata_value, str):\n                    return value.lower() in metadata_value.lower()\n                raise TypeError(\n                    \"Both metadata_value and value should be strings to be used with a \"\n                    \"TEXT_MATCH_INSENSITIVE filter\"\n                )\n            if operator == FilterOperator.ALL:\n                return all(val in metadata_value for val in value)\n            if operator == FilterOperator.ANY:\n                return any(val in metadata_value for val in value)\n\n            raise ValueError(f\"Invalid operator: {operator}\")\n\n        metadata = metadata_lookup_fn(node_id)\n\n        filter_matches_list = []\n        for filter_ in filter_list:\n            if isinstance(filter_, MetadataFilters):\n                raise ValueError(\"Nested MetadataFilters are not supported.\")\n\n            filter_matches = True\n            metadata_value = metadata.get(filter_.key, None)\n            if filter_.operator == FilterOperator.IS_EMPTY:\n                filter_matches = (\n                    metadata_value is None\n                    or metadata_value == \"\"\n                    or metadata_value == []\n                )\n            else:\n                filter_matches = _process_filter_match(\n                    operator=filter_.operator,\n                    value=filter_.value,\n                    metadata_value=metadata_value,\n                )\n\n            filter_matches_list.append(filter_matches)\n","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/vector_stores/utils.py#L146-L182","documentation":"`build_metadata_filter_fn` iterates the entries of a MetadataFilters object and can compose multiple conditions via `condition` (AND/OR/NOT), but it cannot recursively evaluate another MetadataFilters nested inside `filters=[...]`. Nesting is detected with an isinstance check and raises ValueError immediately, before any metadata is evaluated. Use the single-level list plus the condition field, or a store with native nested-filter support.","triggerScenarios":"Constructing `MetadataFilters(filters=[MetadataFilters(filters=[...], condition=FilterCondition.OR)], condition=FilterCondition.AND)` — i.e. AND-of-ORs — and querying a store that filters client-side through build_metadata_filter_fn (SimpleVectorStore and similar).","commonSituations":"Porting boolean filter trees from Pinecone/Qdrant/Weaviate examples into stores without nested-filter support; building advanced faceted search that needs grouped boolean logic; LLM-generated filter JSON that naturally nests groups.","solutions":["Flatten to a single MetadataFilters list with one `condition` (all entries combined with the same AND/OR/NOT).","If you truly need nested boolean logic, use a vector store whose native filtering supports it and pass MetadataFilters through that store's query path.","Emulate nesting by issuing multiple queries and combining results yourself (e.g. run each OR branch, union ids, then apply AND conditions).","Validate your filter structure (no isinstance(entry, MetadataFilters)) before querying."],"exampleFix":"# before\nf = MetadataFilters(\n    filters=[MetadataFilters(filters=[MetadataFilter(\"a\", 1), MetadataFilter(\"b\", 2)], condition=FilterCondition.OR)],\n    condition=FilterCondition.AND,\n)\n\n# after (single level, one condition)\nf = MetadataFilters(\n    filters=[MetadataFilter(\"a\", 1), MetadataFilter(\"b\", 2)],\n    condition=FilterCondition.OR,\n)","handlingStrategy":"validation","validationCode":"from llama_index.core.vector_stores.types import MetadataFilters\n\ndef filters_not_nested(filters: MetadataFilters) -> bool:\n    return not any(isinstance(f, MetadataFilters) for f in filters.filters)","typeGuard":null,"tryCatchPattern":"try:\n    result = store.query(query)\nexcept ValueError as e:\n    if \"Nested MetadataFilters\" in str(e):\n        raise ValueError(\"flatten filters or use a store with native nested filtering\") from e\n    raise","preventionTips":["Keep filter lists flat with a single condition for client-side-filtering stores.","Validate LLM-generated filter JSON against a schema that forbids nesting.","Emulate AND-of-OR with multiple queries and set operations on ids."],"tags":["metadata-filters","nested-filters","not-supported","python"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}