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.

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 by

View on GitHub (pinned to e318778c9b)

Solutions

  1. Guard the call: only invoke bm25_retrieval when query.strip() is non-empty
  2. Return an empty result or a friendly message to the user when the query is blank
  3. 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

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


AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30). Data as JSON: /api/errors/ad4f81079def0a91. Report an issue: GitHub.