From 4098fc04755ea618071570e3a1017ae0c58a8096 Mon Sep 17 00:00:00 2001 From: Mohammad Hijjawi Date: Thu, 17 Sep 2026 11:57:19 +0100 Subject: [PATCH] fix: skip None query input in QueryExpander QueryExpander.run called str.strip on query before checking its type. A None query from a pipeline raised AttributeError. Co-authored-by: Cursor --- haystack/components/query/query_expander.py | 16 ++++++++-------- ...ery-expander-none-query-b7d4e12c90a5f618.yaml | 5 +++++ test/components/query/test_query_expander.py | 14 ++++++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/fix-query-expander-none-query-b7d4e12c90a5f618.yaml diff --git a/haystack/components/query/query_expander.py b/haystack/components/query/query_expander.py index 5279db12abe..2cac9ac07f2 100644 --- a/haystack/components/query/query_expander.py +++ b/haystack/components/query/query_expander.py @@ -198,11 +198,11 @@ def run(self, query: str, n_expansions: int | None = None) -> dict[str, list[str self.warm_up() - response = {"queries": [query] if self.include_original_query else []} - - if not query.strip(): + if not isinstance(query, str) or not query.strip(): logger.warning("Empty query provided to QueryExpander") - return response + return {"queries": [query] if self.include_original_query and isinstance(query, str) else []} + + response = {"queries": [query] if self.include_original_query else []} expansion_count = n_expansions if n_expansions is not None else self.n_expansions if expansion_count <= 0: @@ -268,11 +268,11 @@ async def run_async(self, query: str, n_expansions: int | None = None) -> dict[s await self.warm_up_async() - response = {"queries": [query] if self.include_original_query else []} - - if not query.strip(): + if not isinstance(query, str) or not query.strip(): logger.warning("Empty query provided to QueryExpander") - return response + return {"queries": [query] if self.include_original_query and isinstance(query, str) else []} + + response = {"queries": [query] if self.include_original_query else []} expansion_count = n_expansions if n_expansions is not None else self.n_expansions if expansion_count <= 0: diff --git a/releasenotes/notes/fix-query-expander-none-query-b7d4e12c90a5f618.yaml b/releasenotes/notes/fix-query-expander-none-query-b7d4e12c90a5f618.yaml new file mode 100644 index 00000000000..3b69beb9da1 --- /dev/null +++ b/releasenotes/notes/fix-query-expander-none-query-b7d4e12c90a5f618.yaml @@ -0,0 +1,5 @@ +--- +fixes: + - | + ``QueryExpander`` now returns an empty query list when ``query`` is ``None`` or not a string, + instead of raising ``AttributeError`` on ``str.strip``. diff --git a/test/components/query/test_query_expander.py b/test/components/query/test_query_expander.py index c932f6af257..951369b8a7b 100644 --- a/test/components/query/test_query_expander.py +++ b/test/components/query/test_query_expander.py @@ -134,6 +134,20 @@ def test_run_whitespace_only_query(self, monkeypatch, caplog): assert result["queries"] == ["\t\n \r"] assert "Empty query provided" in caplog.text + def test_run_none_query(self, monkeypatch, caplog): + monkeypatch.setenv("OPENAI_API_KEY", "test-key-12345") + expander = QueryExpander() + with caplog.at_level(logging.WARNING): + result = expander.run(None) # type: ignore[arg-type] + assert result["queries"] == [] + assert "Empty query provided" in caplog.text + + def test_run_none_query_include_original(self, monkeypatch): + monkeypatch.setenv("OPENAI_API_KEY", "test-key-12345") + expander = QueryExpander(include_original_query=False) + result = expander.run(None) # type: ignore[arg-type] + assert result["queries"] == [] + def test_run_generator_no_replies(self, mock_chat_generator): mock_chat_generator.run.return_value = {"replies": []} expander = QueryExpander(chat_generator=mock_chat_generator)