headroomlabs-ai/headroom · error · ValueError

Either query_vector or query_text must be provided

Error message

Either query_vector or query_text must be provided

What it means

Raised by HNSWVectorIndex.search when the VectorFilter carries neither query_vector nor query_text. The search API requires at least one query representation; an empty filter is a caller bug rather than a valid 'match all' request.

Source

Thrown at headroom/memory/adapters/hnsw.py:595

        """Search for similar memories using vector similarity.

        Args:
            filter: Vector search filter with query and constraints.

        Returns:
            List of search results sorted by similarity (descending).

        Raises:
            ValueError: If neither query_vector nor query_text is provided,
                       or if query_text is provided (embedding must be done externally).
        """
        if filter.query_vector is None:
            if filter.query_text is not None:
                raise ValueError(
                    "query_text provided but HNSWVectorIndex does not embed text. "
                    "Provide query_vector directly or use an Embedder first."
                )
            raise ValueError("Either query_vector or query_text must be provided")

        query_vector = np.asarray(filter.query_vector, dtype=np.float32)
        if query_vector.shape[0] != self._dimension:
            raise ValueError(
                f"Query vector dimension {query_vector.shape[0]} does not match "
                f"index dimension {self._dimension}"
            )

        with self._lock:
            # NOTE: Use len() directly, not self.size - Lock is not reentrant!
            current_size = len(self._memory_to_hnsw)
            if current_size == 0:
                return []

            # Search with more results than needed to account for filtering
            # Retrieve extra candidates to improve recall after filtering
            k_with_buffer = min(
                filter.top_k * 10,  # Get 10x candidates for filtering

View on GitHub (pinned to 322425c43b)

Solutions

  1. Ensure either query_vector or query_text is populated before calling search.
  2. If the query source can be None, validate at the API boundary and return a 400 instead of calling the index.
  3. For listing without similarity, use the store's listing API, not vector search.

Example fix

// before
f = VectorFilter(user_id="u1")  # no query at all
results = await index.search(f)

// after
if query is None:
    raise HTTPException(400, "query required")
results = await index.search(VectorFilter(query_vector=await embedder.embed(query), user_id="u1"))
Defensive patterns

Strategy: validation

Validate before calling

if filter.query_vector is None and filter.query_text is None:
    raise ValueError("Vector search requires a query")
results = await index.search(filter)

Prevention

When it happens

Trigger: Constructing VectorFilter() with only constraint fields (user_id, session_id filters) and no query; a variable holding the query string ends up None and is assigned to query_text.

Common situations: Optional query parameters flowing from an API request defaulting to None; building filters dynamically where the query key is missing; expecting filter-only search semantics.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/326c0cd422e86ea8. Report an issue: GitHub.