RyanCodrai/turbovec · error · ValueError

query_embedding dim {qvec.shape[1]} does not match store dim

Error message

query_embedding dim {qvec.shape[1]} does not match store dim {expected_dim}

What it means

Raised in embedding_retrieval when the query vector's width differs from the store's committed dimension (self._index.dim). The query was embedded with a different model or configuration than the documents in the store, so similarity scoring would be meaningless.

Source

Thrown at turbovec-python/python/turbovec/haystack.py:625

        # Up-front validation, matching the reference: an empty or
        # non-numeric query embedding is a caller error regardless of
        # whether the store happens to be empty (issue #301). `Real`
        # rather than the reference's `isinstance(..., float)` so numpy
        # scalars and ints are accepted.
        if len(query_embedding) == 0 or not isinstance(query_embedding[0], Real):
            raise ValueError("query_embedding should be a non-empty list of floats.")

        if self.count_documents() == 0:
            return []

        qvec = np.asarray(query_embedding, dtype=np.float32)
        if qvec.ndim == 1:
            qvec = qvec[None, :]
        # By this point n_documents > 0, so the index has a committed dim.
        expected_dim = self._index.dim
        if qvec.shape[1] != expected_dim:
            raise ValueError(
                f"query_embedding dim {qvec.shape[1]} does not match store dim {expected_dim}"
            )
        # Cosine mode: normalize the query so the raw score against unit
        # document vectors is true cosine similarity.
        if self._vectors_normalized:
            qvec = l2_normalize_rows(qvec)
        if not qvec.flags["C_CONTIGUOUS"]:
            qvec = np.ascontiguousarray(qvec)

        if not filters:
            fetch_k = min(top_k, self.count_documents())
            scores, handles = self._index.search(qvec, fetch_k)
        else:
            self._validate_filters(filters)
            for _attempt in range(8):
                # Resolve filter → handle allowlist by walking the in-memory
                # doc table once. This is the same O(N) cost as the old
                # post-filter pass, just moved upfront so the kernel can

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Embed queries with the same embedder used to index the documents.
  2. Create/rebuild the store with the current embedder if the model intentionally changed.
  3. Catch the ValueError to surface embedder/store mismatch in retrieval pipelines instead of returning wrong results.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at turbovec-python/python/turbovec/haystack.py:625 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of RyanCodrai/turbovec@ccab9f325e (2026-09-06). Data as JSON: /api/errors/91f7a26e637c3a83. Report an issue: GitHub.