Skip to content

Commit 1a68ffa

Browse files
fix: raise FilterError on unknown metadata filter operators (#11795)
Co-authored-by: David S. Batista <dsbatista@gmail.com>
1 parent 022ccea commit 1a68ffa

3 files changed

Lines changed: 66 additions & 0 deletions

File tree

haystack/utils/filters.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ def _logic_condition(condition: dict[str, Any], document: Document | ByteStream)
173173
msg = f"'conditions' key missing in {condition}"
174174
raise FilterError(msg)
175175
operator: str = condition["operator"]
176+
if operator not in LOGICAL_OPERATORS:
177+
msg = f"Unknown logical operator '{operator}'. Valid operators are: {sorted(LOGICAL_OPERATORS)}"
178+
raise FilterError(msg)
176179
conditions: list[dict[str, Any]] = condition["conditions"]
177180
return LOGICAL_OPERATORS[operator](document=document, conditions=conditions)
178181

@@ -214,5 +217,8 @@ def _comparison_condition(condition: dict[str, Any], document: Document | ByteSt
214217
else:
215218
document_value = getattr(document, field)
216219
operator: str = condition["operator"]
220+
if operator not in COMPARISON_OPERATORS:
221+
msg = f"Unknown comparison operator '{operator}'. Valid operators are: {sorted(COMPARISON_OPERATORS)}"
222+
raise FilterError(msg)
217223
filter_value: Any = condition["value"]
218224
return COMPARISON_OPERATORS[operator](filter_value=filter_value, value=document_value)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
fixes:
3+
- |
4+
Metadata filters that use an unsupported operator now raise a clear ``FilterError``
5+
that lists the valid operators, instead of a cryptic ``KeyError``. For example, a
6+
typo such as ``{"field": "meta.year", "operator": "gt", "value": 2000}`` (instead of
7+
``">"``) previously surfaced as ``KeyError: 'gt'``. This applies to both comparison
8+
operators and logical operators (``AND``, ``OR``, ``NOT``).

test/utils/test_filters.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,23 @@ def test_document_matches_filter(filters, document, expected_result):
566566
pytest.param({"operator": "==", "value": "test"}, id="Missing condition field key"),
567567
pytest.param({"field": "meta.name", "value": "test"}, id="Missing condition operator key"),
568568
pytest.param({"field": "meta.name", "operator": "=="}, id="Missing condition value key"),
569+
# Unknown operators
570+
pytest.param({"field": "meta.page", "operator": "gt", "value": 10}, id="Unknown comparison operator"),
571+
pytest.param(
572+
{"operator": "XOR", "conditions": [{"field": "meta.page", "operator": "==", "value": 10}]},
573+
id="Unknown logical operator",
574+
),
575+
pytest.param(
576+
{
577+
"operator": "AND",
578+
"conditions": [{"operator": "XOR", "conditions": [{"field": "meta.page", "operator": "==", "value": 10}]}],
579+
},
580+
id="Unknown nested logical operator",
581+
),
582+
pytest.param(
583+
{"operator": "and", "conditions": [{"field": "meta.page", "operator": "==", "value": 10}]},
584+
id="Lowercase logical operator",
585+
),
569586
]
570587

571588

@@ -574,3 +591,38 @@ def test_document_matches_filter_raises_error(filters):
574591
with pytest.raises(FilterError):
575592
document = Document(meta={"page": 10})
576593
document_matches_filter(filters, document)
594+
595+
596+
@pytest.mark.parametrize(
597+
"filters,expected_message",
598+
[
599+
pytest.param(
600+
{"field": "meta.page", "operator": "gt", "value": 10},
601+
"Unknown comparison operator 'gt'",
602+
id="Unknown comparison operator",
603+
),
604+
pytest.param(
605+
{"operator": "XOR", "conditions": [{"field": "meta.page", "operator": "==", "value": 10}]},
606+
"Unknown logical operator 'XOR'",
607+
id="Unknown logical operator",
608+
),
609+
pytest.param(
610+
{
611+
"operator": "AND",
612+
"conditions": [
613+
{"operator": "XOR", "conditions": [{"field": "meta.page", "operator": "==", "value": 10}]}
614+
],
615+
},
616+
"Unknown logical operator 'XOR'",
617+
id="Unknown nested logical operator",
618+
),
619+
pytest.param(
620+
{"operator": "and", "conditions": [{"field": "meta.page", "operator": "==", "value": 10}]},
621+
"Unknown logical operator 'and'",
622+
id="Lowercase logical operator",
623+
),
624+
],
625+
)
626+
def test_document_matches_filter_unknown_operator_error_message(filters, expected_message):
627+
with pytest.raises(FilterError, match=expected_message):
628+
document_matches_filter(filters, Document(meta={"page": 10}))

0 commit comments

Comments
 (0)