RyanCodrai/turbovec · error · TypeError

metadatas[{i}] must be a dict, got {type(meta).__name__}

Error message

metadatas[{i}] must be a dict, got {type(meta).__name__}

What it means

TypeError raised in _store_texts_and_vectors when a metadatas entry is not a dict (e.g. None). Validation happens for the whole batch before any state change: previously a bad entry blew up as dict(None) mid-loop after vectors were added to the index, desyncing the docstore and index (and persisting the corruption via dump).

Source

Thrown at turbovec-python/python/turbovec/langchain.py:375

    def _store_texts_and_vectors(
        self,
        texts_list: list[str],
        vectors: np.ndarray,
        metadatas: list[dict],
        ids: list[str],
    ) -> list[str]:
        if vectors.ndim != 2:
            raise ValueError(f"expected 2D embedding batch, got {vectors.ndim}D")

        # Validate every metadata entry before touching any state. A bad
        # entry (e.g. None) previously blew up as `dict(None)` mid-loop,
        # *after* the vectors had been added to the index — leaving the
        # docstore and index desynced in memory (and dump() would persist
        # the corruption). The reference InMemoryVectorStore rejects bad
        # metadata with a named error; mirror that here.
        for i, meta in enumerate(metadatas):
            if not isinstance(meta, dict):
                raise TypeError(
                    f"metadatas[{i}] must be a dict, "
                    f"got {type(meta).__name__}"
                )

        # Dedup intra-batch duplicate ids, keeping the last occurrence —
        # matches InMemoryVectorStore, whose dict store silently overwrites
        # on a repeated id. Without this every row is added to the index but
        # _str_to_u64 keeps only the last handle per id, orphaning the
        # earlier vectors. The returned id list still mirrors the input
        # (one entry per input text), as the reference does.
        result_ids = ids
        keep = resolve_duplicates(ids, DuplicatePolicy.KEEP_LAST)
        if len(keep) != len(ids):
            ids = [ids[i] for i in keep]
            texts_list = [texts_list[i] for i in keep]
            metadatas = [metadatas[i] for i in keep]
            vectors = vectors[keep]

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Pass a dict (possibly empty) for every text's metadata, matching InMemoryVectorStore's contract.
  2. Fix upstream Document construction that produced None metadata.
  3. Catch the TypeError in ingestion code — it is raised before any mutation, so the store remains consistent.
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at turbovec-python/python/turbovec/langchain.py:375 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/27aa325e49135e0f. Report an issue: GitHub.