deepset-ai/haystack · error
Query should be a non-empty string
Error message
Query should be a non-empty string
What it means
InMemoryDocumentStore.bm25_retrieval raises ValueError when the query argument is empty (or falsy). BM25 scoring is undefined for an empty query, so the store fails fast instead of returning meaningless results.
Solutions
- Guard the call: only invoke bm25_retrieval when query.strip() is non-empty
- Return an empty result or a friendly message to the user when the query is blank
- Fix the upstream component so it emits a real query instead of an empty string
Example fix
// before
results = store.bm25_retrieval(query=user_input, top_k=10)
// after
if not user_input or not user_input.strip():
results = []
else:
results = store.bm25_retrieval(query=user_input, top_k=10) Defensive patterns
Strategy: validation
Validate before calling
if not isinstance(query, str) or not query.strip():
raise ValueError("query must be a non-empty string before bm25_retrieval") Type guard
def is_non_empty_str(x) -> bool:
return isinstance(x, str) and bool(x.strip()) Try / catch
try:
docs = store.bm25_retrieval(query=query, top_k=10)
except ValueError as e:
if "Query should be a non-empty string" in str(e):
docs = [] # or return a 'no query provided' message
else:
raise Prevention
- Validate/normalize user input before retrieval; reject blank queries early
- Check upstream components (e.g. query reformulators) don't emit empty strings
- Strip and re-check the query after any preprocessing that could empty it
When it happens
Trigger: Calling bm25_retrieval(query="") or bm25_retrieval(query=None); passing a query variable that was never filled (empty string from a failed upstream component or blank user input).
Common situations: Chat pipelines receiving empty user messages, templates leaving a placeholder unfilled, stripping/normalizing the query down to an empty string before retrieval.
Related errors
- A `ChatMessage` must contain at least one `TextContent`…
- Aggregate score missing for
- All separators must be strings.
- `async_function` must be a coroutine function defined with…
- `async_function` must be a coroutine function defined with…
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/ad4f81079def0a91.
Report an issue: GitHub.
Appendix: source
Thrown at haystack/document_stores/in_memory/document_store.py:740
sorted_keys = sorted(unique_values, key=lambda k: (k[1], k[0]))
paginated_keys = sorted_keys[from_ : from_ + size]
return [unique_values[k] for k in paginated_keys], len(sorted_keys)
def bm25_retrieval(
self, query: str, filters: dict[str, Any] | None = None, top_k: int = 10, scale_score: bool = False
) -> list[Document]:
"""
Retrieves documents that are most relevant to the query using BM25 algorithm.
:param query: The query string.
:param filters: A dictionary with filters to narrow down the search space.
:param top_k: The number of top documents to retrieve. Default is 10.
:param scale_score: Whether to scale the scores of the retrieved documents. Default is False.
:returns: A list of the top_k documents most relevant to the query.
"""
if not query:
raise ValueError("Query should be a non-empty string")
content_type_filter = {"field": "content", "operator": "!=", "value": None}
if filters:
if "operator" not in filters:
raise ValueError(
"Invalid filter syntax. See https://docs.haystack.deepset.ai/docs/metadata-filtering for details."
)
filters = {"operator": "AND", "conditions": [content_type_filter, filters]}
else:
filters = content_type_filter
all_documents = self.filter_documents(filters=filters)
if len(all_documents) == 0:
logger.info("No documents found for BM25 retrieval. Returning empty list.")
return []
# A tokenless corpus (every stored document has empty content) has no vocabulary and an
# average document length of zero, which would make all three BM25 algorithms divide byView on GitHub (pinned to e318778c9b)