langchain-ai/langchain · error · ValueError

The number of metadatas must match the number of texts.Got {

Error message

The number of metadatas must match the number of texts.Got {len(metadatas)} metadatas and {len(texts_)} texts.

What it means

Raised by the base `VectorStore.add_texts` compatibility shim when the subclass implements `add_documents`/`upsert` (so the shim converts texts+metadatas into `Document` objects) but the supplied `metadatas` list length differs from the number of `texts`. Each text must map one-to-one onto a metadata dict, otherwise `Document` construction would be ambiguous.

Source

Thrown at libs/core/langchain_core/vectorstores/base.py:84

            List of IDs from adding the texts into the `VectorStore`.

        Raises:
            ValueError: If the number of metadatas does not match the number of texts.
            ValueError: If the number of IDs does not match the number of texts.
        """
        if type(self).add_documents != VectorStore.add_documents:
            # This condition is triggered if the subclass has provided
            # an implementation of the upsert method.
            # The existing add_texts
            texts_: Sequence[str] = (
                texts if isinstance(texts, (list, tuple)) else list(texts)
            )
            if metadatas and len(metadatas) != len(texts_):
                msg = (
                    "The number of metadatas must match the number of texts."
                    f"Got {len(metadatas)} metadatas and {len(texts_)} texts."
                )
                raise ValueError(msg)
            metadatas_ = iter(metadatas) if metadatas else cycle([{}])
            ids_: Iterator[str | None] = iter(ids) if ids else cycle([None])
            docs = [
                Document(id=id_, page_content=text, metadata=metadata_)
                for text, metadata_, id_ in zip(texts, metadatas_, ids_, strict=False)
            ]
            if ids is not None:
                # For backward compatibility
                kwargs["ids"] = ids

            return self.add_documents(docs, **kwargs)
        msg = f"`add_texts` has not been implemented for {self.__class__.__name__} "
        raise NotImplementedError(msg)

    @property
    def embeddings(self) -> Embeddings | None:
        """Access the query embedding object if available."""
        logger.debug(

View on GitHub (pinned to e32fa9a52e)

Solutions

  1. Make `metadatas` exactly one entry per text: `assert len(metadatas) == len(texts)` before the call and fix the producer.
  2. If all texts share metadata, either omit `metadatas` or expand it: `metadatas=[meta] * len(texts)`.
  3. Pair them at construction: `metadatas = [{'source': s} for s in sources]` built from the same iterable that produced `texts`.

Example fix

# before
texts = [d.page_content for d in docs]
metadatas = [m for m in raw_metadata if m]  # filtered -> length mismatch
store.add_texts(texts, metadatas)

# after
texts = [d.page_content for d in docs]
metadatas = [d.metadata for d in docs]  # 1:1 with texts
store.add_texts(texts, metadatas)
Defensive patterns

Strategy: validation

Validate before calling

def prepare_batch(texts, metadatas):
    if metadatas is not None and len(list(metadatas)) != len(list(texts)):
        raise ValueError(f"texts ({len(texts)}) and metadatas ({len(metadatas)}) must align")
    return texts, metadatas

Prevention

When it happens

Trigger: Calling `vectorstore.add_texts(texts=[...n items...], metadatas=[...m items...])` with `m != n` on a store that only overrides `add_documents`. Generator inputs are materialized first, so lazy iterators with unexpected lengths also trigger it.

Common situations: Building metadata in a separate comprehension that skips rows (e.g. filtering empty metadata) so lengths drift; passing a single metadata dict instead of a list of dicts; chunking text without chunking metadata correspondingly.

Related errors


AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14). Data as JSON: /api/errors/972e96817b2dd449. Report an issue: GitHub.