RyanCodrai/turbovec · error · ValueError

expected 2D embedding batch, got {vectors.ndim}D

Error message

expected 2D embedding batch, got {vectors.ndim}D

What it means

Raised in TurboQuantVectorDb.insert when the per-document embeddings stacked via np.asarray do not form a 2D (N, dim) array. This fires when the batch is empty (0D) or documents carry ragged/non-array embeddings (1D or object arrays), i.e. the embedding step produced something that is not a uniform matrix of vectors.

Source

Thrown at turbovec-python/python/turbovec/agno.py:510

        # None/len check instead of truthiness: `not <ndarray>` raises the
        # numpy truth-value-ambiguous ValueError (issue #135).
        missing = [
            doc
            for doc in documents
            if doc.embedding is None or len(doc.embedding) == 0
        ]
        if missing:
            ids = [doc.id or "<no id>" for doc in missing]
            raise ValueError(
                f"failed to embed {len(missing)} document(s): {ids}"
            )

        # Batch the entire `documents` list into a single add_with_ids call.
        # Per-document inserts would invalidate the SIMD-blocked cache
        # between every doc.
        vectors = np.asarray([doc.embedding for doc in documents], dtype=np.float32)
        if vectors.ndim != 2:
            raise ValueError(
                f"expected 2D embedding batch, got {vectors.ndim}D"
            )
        if vectors.shape[1] != self.dimensions:
            raise ValueError(
                f"embedding dim {vectors.shape[1]} does not match "
                f"index dim {self.dimensions}"
            )
        if not vectors.flags["C_CONTIGUOUS"]:
            vectors = np.ascontiguousarray(vectors)
        # Cosine mode: L2-normalize outside the lock (pure computation,
        # like the embedding step) so the kernel's raw score is true
        # cosine similarity. Zero rows pass through unchanged.
        if self.distance == Distance.cosine:
            vectors = l2_normalize_rows(vectors)

        # Build every side-car payload BEFORE mutating any state (pure
        # computation, no store reads).
        prepared = []

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Ensure every document has an embedding before insert; the preceding guard already rejects missing/empty embeddings, so check for ragged or scalar embeddings from the embedder.
  2. Verify documents is a non-empty list of embedding-bearing objects so np.asarray builds an (N, dim) float32 matrix.
  3. Inspect vectors.ndim at the call site to confirm whether the input collapsed to 0D (empty batch) or 1D (single vector passed instead of a batch).
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at turbovec-python/python/turbovec/agno.py:510 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/28d56bdfa65f1f6b. Report an issue: GitHub.