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
- Pass a dict (possibly empty) for every text's metadata, matching InMemoryVectorStore's contract.
- Fix upstream Document construction that produced None metadata.
- 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.