deepset-ai / deepset-ai/haystack
DocumentJoiner positional weights follow Variadic arrival order, not connect() order
@anakin87 is already working on this.
Since Sep 7, 2026.
- Dominant language
- Python
- Stars
- 26.6k
- Forks
- 3.2k
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 194
Description
Describe the bug
DocumentJoiner weights=[w0, w1, …] are zipped positionally onto the Variadic documents list. That list order is not Pipeline.connect() order:
- sync
run: independent senders run in alphabetical component-name order, so weights bind to alphabetical arrival run_async: completion/arrival order (nondeterministic)
Users reasonably assume connect(sparse); connect(dense) + weights=[sparse_w, dense_w] maps weights to those senders. The same graph + weights can therefore produce different hybrid scores.
Related: if a predecessor never runs (e.g. a ConditionalRouter branch is skipped), len(document_lists) < len(weights) and zip(..., strict=True) raises ValueError / PipelineRuntimeError.
To Reproduce
from haystack import Pipeline, Document, component
from haystack.components.joiners import DocumentJoiner
@component
class EmitDocs:
def __init__(self, docs):
self.docs = docs
@component.output_types(documents=list[Document])
def run(self):
return {documents: self.docs}
p = Pipeline()
# alphabetical: dense < sparse — opposite of connect order below
p.add_component(dense, EmitDocs([Document(content=shared, score=10.0)]))
p.add_component(sparse, EmitDocs([Document(content=shared, score=1.0)]))
p.add_component(joiner, DocumentJoiner(join_mode=merge, weights=[0.9, 0.1], sort_by_score=False))
p.connect(sparse, joiner) # intended weight 0.9
p.connect(dense, joiner) # intended weight 0.1
score = p.run({})[joiner][documents][0].score
print(score)
# actual today: 9.1 (dense*0.9 + sparse*0.1)
# expected if connect order: 1.9 (sparse*0.9 + dense*0.1)
Skipped-branch crash:
from haystack.components.routers import ConditionalRouter
# router -> branch_a / branch_b -> DocumentJoiner(weights=[0.5, 0.5])
# run with only branch_a selected -> zip length mismatch
Expected behavior
Weights follow connect() / InputSocket.senders order. Missing senders pad as empty lists so weighted merge/RRF does not crash.
Related
- Closed discussion of alphabetical auto-variadic ordering: #10979 (auto-promoted list sockets; this issue is about explicit
Variadic+ DocumentJoiner weights)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.