langchain-ai/langchain · error · ValueError
source_id_key should be either None, a string or a callable.
Error message
source_id_key should be either None, a string or a callable. Got {source_id_key} of type {type(source_id_key)}. What it means
Raised by `_get_source_id_assigner` in `langchain_core.indexing.api`. During indexing with incremental/scoped_full cleanup, each Document must be traced back to an upstream source (e.g. a file path or URL) so stale copies can be deleted. The `source_id_key` parameter tells the indexer how to extract that ID and must be None, a metadata key name, or a callable — anything else is rejected.
Source
Thrown at libs/core/langchain_core/indexing/api.py:136
if batch:
yield batch
def _get_source_id_assigner(
source_id_key: str | Callable[[Document], str] | None,
) -> Callable[[Document], str | None]:
"""Get the source id from the document."""
if source_id_key is None:
return lambda _doc: None
if isinstance(source_id_key, str):
return lambda doc: doc.metadata[source_id_key]
if callable(source_id_key):
return source_id_key
msg = ( # type: ignore[unreachable]
f"source_id_key should be either None, a string or a callable. "
f"Got {source_id_key} of type {type(source_id_key)}."
)
raise ValueError(msg)
def _deduplicate_in_order(
hashed_documents: Iterable[Document],
) -> Iterator[Document]:
"""Deduplicate a list of hashed documents while preserving order."""
seen: set[str] = set()
for hashed_doc in hashed_documents:
if hashed_doc.id not in seen:
# At this stage, the id is guaranteed to be a string.
# Avoiding unnecessary run time checks.
seen.add(cast("str", hashed_doc.id))
yield hashed_doc
class IndexingException(LangChainException):
"""Raised when an indexing operation fails."""View on GitHub (pinned to e32fa9a52e)
Solutions
- Use a metadata key string: `source_id_key="source"` and ensure each document's metadata contains it.
- Or use a callable: `source_id_key=lambda doc: doc.metadata["file_path"]`.
- Or pass None when using cleanup=None/'full', which does not need source IDs.
Example fix
# before index(vs, docs, rm, source_id_key=0, cleanup="incremental") # after index(vs, docs, rm, source_id_key="source", cleanup="incremental")
Defensive patterns
Strategy: type-guard
Validate before calling
if source_id_key is not None and not isinstance(source_id_key, (str,)) and not callable(source_id_key):
raise TypeError(f"bad source_id_key: {source_id_key!r}")
index(vs, docs, rm, source_id_key=source_id_key, cleanup="incremental") Type guard
def is_valid_source_id_key(k) -> bool:
return k is None or isinstance(k, str) or callable(k) Prevention
- Parse config-driven source_id_key as a string and reject other types at load time.
- Prefer callables for non-trivial extraction; they also give better error control.
When it happens
Trigger: Passing `source_id_key=123`, a tuple, or a list to `index()`/`aindex()`; passing a dict-like object that is not a str; passing a non-callable object that was intended to be a function (e.g. referencing an attribute instead of the method).
Common situations: Config-driven pipelines where source_id_key comes from YAML/JSON and is parsed as a non-string type; typos like `source_id_key=doc.metadata["source"]` (evaluates to a value, but if the metadata value is not a str — e.g. an int — this error fires at a different layer; here the error is on the key parameter itself).
Related errors
- cleanup should be one of 'incremental', 'full', 'scoped_full
- Batch size must be a positive integer, got {size}.
- Unsupported hashing algorithm: {algorithm}
- The delete operation to VectorStore failed.
- The delete operation to DocumentIndex failed.
AI-assisted analysis of langchain-ai/langchain@e32fa9a52e (2026-08-14).
Data as JSON: /api/errors/e1b284313a6877db.
Report an issue: GitHub.