deepset-ai/haystack · error
The length of the metadata list must match the number of…
Error message
The length of the metadata list must match the number of sources.
What it means
normalize_metadata aligns per-source metadata with the number of sources. When meta is a list, its length must equal sources_count; otherwise ValueError is raised. This ensures each source gets exactly one metadata dict in converter run() calls.
Solutions
- Make the meta list exactly the same length as sources (one dict per source).
- Pass a single dict instead — it is automatically deep-copied for every source.
- Pass meta=None to get an empty dict per source.
Example fix
# before
converter.run(sources=[a, b, c], meta=[{"author": "x"}]) # 1 vs 3
# after
converter.run(sources=[a, b, c], meta=[{"author": "x"}, {"author": "x"}, {"author": "x"}])
# or simply:
converter.run(sources=[a, b, c], meta={"author": "x"}) Defensive patterns
Strategy: validation
Validate before calling
def check_meta(meta, sources):
if isinstance(meta, list) and len(meta) != len(sources):
raise ValueError(f"meta length {len(meta)} != sources length {len(sources)}")
check_meta(meta, sources)
converter.run(sources=sources, meta=meta) Try / catch
try:
result = converter.run(sources=sources, meta=meta)
except ValueError as e:
if "length of the metadata list" in str(e):
result = converter.run(sources=sources, meta=meta[:len(sources)] if len(meta) > len(sources) else meta)
else:
raise Prevention
- Prefer a single shared dict over a list when all sources need identical metadata
- Build meta with zip(sources, meta_dicts) so lengths are tied together structurally
- Assert len(meta) == len(sources) right before the call in batch pipelines
When it happens
Trigger: Calling a converter's run(sources=[...], meta=[{...},...]) where len(meta) != len(sources) — e.g. one metadata dict for three files, or extra dicts left over from a previous batch.
Common situations: Reusing a cached meta list across batches of different size; building meta in a loop that skips failed sources; hardcoded meta for a fixed file count then changing the file list.
Related errors
- meta must be either None, a dictionary or a list of…
- CSVToDocument: quotechar must be a single character.
- Document with ID ' ' is missing the ' ' key in its…
- LLM evaluator expects all input lists to have the same…
- The number of predictions and labels must be the same.
AI-assisted analysis of deepset-ai/haystack@e318778c9b (2026-08-30).
Data as JSON: /api/errors/c57344a2ee095146.
Report an issue: GitHub.
Appendix: source
Thrown at haystack/components/converters/utils.py:80
Given all the possible value of the meta input for a converter (None, dictionary or list of dicts),
makes sure to return a list of dictionaries of the correct length for the converter to use.
:param meta: the meta input of the converter, as-is
:param sources_count: the number of sources the converter received
:returns: a list of dictionaries of the make length as the sources list
Each source always gets its own independent dictionary. When ``meta`` is ``None`` or a single
dictionary, a separate copy is returned for every source so that mutating one source's metadata
downstream does not leak into the others.
"""
if meta is None:
return [{} for _ in range(sources_count)]
if isinstance(meta, dict):
return [deepcopy(meta) for _ in range(sources_count)]
if isinstance(meta, list):
if sources_count != len(meta):
raise ValueError("The length of the metadata list must match the number of sources.")
return meta
raise ValueError("meta must be either None, a dictionary or a list of dictionaries.")
View on GitHub (pinned to e318778c9b)