RyanCodrai/turbovec · error · TypeError

ids[{pos}] is {id_!r} of type {type(id_).__name__}; ids must

Error message

ids[{pos}] is {id_!r} of type {type(id_).__name__}; ids must be str (or None for a generated UUID). Non-str ids are rejected because JSON persistence coerces keys to str, silently colliding with any equal-looking str id (e.g. 2 vs '2') on dump/load.

What it means

TypeError raised in _normalize_ids (from add_texts/aadd_texts) when an id is neither str nor None — e.g. int, bool (a subclass of int). Deliberately stricter than the reference InMemoryVectorStore: JSON persistence coerces dict keys to str, so an int id 2 would silently collide with the str id '2' on dump/load, corrupting the store.

Source

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

        Any other non-``str`` id raises ``TypeError``. This is a
        deliberate deviation from the reference InMemoryVectorStore,
        which accepts e.g. an ``int`` id and then corrupts it: JSON
        persistence coerces every key to ``str``, so ``2`` and ``"2"``
        are two documents in memory but collapse to one on ``dump``/
        ``load`` — silent data loss plus an out-of-sync side-car.
        Rejecting at the add boundary (the declared contract is
        ``list[str]``) makes that state unrepresentable. ``bool`` is a
        subclass of ``int`` and is rejected like any other non-str type:
        only ``str`` instances (and ``None``) are accepted.
        """
        normalized: list[str] = []
        for pos, id_ in enumerate(ids):
            if id_ is None:
                normalized.append(str(uuid.uuid4()))
            elif isinstance(id_, str):
                normalized.append(id_)
            else:
                raise TypeError(
                    f"ids[{pos}] is {id_!r} of type {type(id_).__name__}; "
                    "ids must be str (or None for a generated UUID). "
                    "Non-str ids are rejected because JSON persistence "
                    "coerces keys to str, silently colliding with any "
                    "equal-looking str id (e.g. 2 vs '2') on dump/load."
                )
        return normalized

    def add_texts(
        self,
        texts: Iterable[str],
        metadatas: list[dict] | None = None,
        ids: list[str] | None = None,
        **_: Any,
    ) -> list[str]:
        texts_list = list(texts)
        if not texts_list:
            return []

View on GitHub (pinned to ccab9f325e)

Solutions

  1. Pass str ids (or None to get a generated UUID): ids=['2'] instead of ids=[2].
  2. Convert caller-supplied ids with str(id) at the boundary — but only when no int/str collision is possible.
  3. Catch the TypeError in ingestion code to reject non-str id schemes up front.
Defensive patterns

Strategy: type-guard

When it happens

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