Skip to content

Commit b4bb6bd

Browse files
RafaelJohn9sjrl
andauthored
Fix/informative error message (#9661)
* fix: more informative error message when two components connect * chore: releasenote * fix: (PipelineBase.connect) disable C901 complexity check using noqa * fix: (PipelineBase:connect) provided two exceptions: when is not defined && is not defined * test: added tests for the related issues * Update haystack/core/pipeline/base.py --------- Co-authored-by: Sebastian Husch Lee <[email protected]>
1 parent 33b2b83 commit b4bb6bd

File tree

3 files changed

+46
-2
lines changed

3 files changed

+46
-2
lines changed

haystack/core/pipeline/base.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ def remove_component(self, name: str) -> Component:
417417

418418
return instance
419419

420-
def connect(self, sender: str, receiver: str) -> "PipelineBase": # noqa: PLR0915 PLR0912
420+
def connect(self, sender: str, receiver: str) -> "PipelineBase": # noqa: PLR0915 PLR0912 C901 pylint: disable=too-many-branches
421421
"""
422422
Connects two components together.
423423
@@ -456,13 +456,20 @@ def connect(self, sender: str, receiver: str) -> "PipelineBase": # noqa: PLR091
456456
except KeyError as exc:
457457
raise ValueError(f"Component named {receiver_component_name} not found in the pipeline.") from exc
458458

459+
if not sender_sockets:
460+
raise PipelineConnectError(
461+
f"'{sender_component_name}' does not have any output connections. "
462+
f"Please check that the output types of '{sender_component_name}.run' are set, "
463+
f"for example by using the '@component.output_types' decorator."
464+
)
465+
459466
# If the name of either socket is given, get the socket
460467
sender_socket: Optional[OutputSocket] = None
461468
if sender_socket_name:
462469
sender_socket = sender_sockets.get(sender_socket_name)
463470
if not sender_socket:
464471
raise PipelineConnectError(
465-
f"'{sender} does not exist. "
472+
f"'{sender}' does not exist. "
466473
f"Output connections of {sender_component_name} are: "
467474
+ ", ".join([f"{name} (type {_type_name(socket.type)})" for name, socket in sender_sockets.items()])
468475
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fixes:
2+
- |
3+
Return a more informative error message when attempting to connect two components and the sender component does not have any OutputSockets defined.

test/core/pipeline/test_pipeline_base.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,40 @@ def test_remove_component_allows_you_to_reuse_the_component(self):
259259
# instance = pipe2.get_component("some")
260260
# assert instance == component
261261

262+
def test_connect_with_nonexistent_output_socket_name(self):
263+
"""Test connecting using a non-existent output socket name."""
264+
comp1 = component_class("Comp1", output_types={"output": int})()
265+
comp2 = component_class("Comp2", input_types={"value": int})()
266+
pipe = PipelineBase()
267+
pipe.add_component("comp1", comp1)
268+
pipe.add_component("comp2", comp2)
269+
270+
with pytest.raises(PipelineConnectError) as excinfo:
271+
pipe.connect("comp1.value", "comp2.value")
272+
273+
assert "'comp1.value' does not exist" in str(excinfo.value)
274+
assert "Output connections of comp1 are: output (type int)" in str(excinfo.value)
275+
276+
def test_connect_with_no_output_sockets(self):
277+
"""Test connecting from a component that has no output sockets at all."""
278+
279+
@component
280+
class NoOutputComponent:
281+
def run(self):
282+
pass
283+
284+
comp1 = NoOutputComponent()
285+
comp2 = component_class("Comp2", input_types={"value": int})()
286+
pipe = PipelineBase()
287+
pipe.add_component("comp1", comp1)
288+
pipe.add_component("comp2", comp2)
289+
290+
with pytest.raises(PipelineConnectError) as excinfo:
291+
pipe.connect("comp1.value", "comp2.value")
292+
293+
assert "'comp1' does not have any output connections" in str(excinfo.value)
294+
assert "@component.output_types" in str(excinfo.value)
295+
262296
# UNIT
263297
def test_get_component_name(self):
264298
pipe = PipelineBase()

0 commit comments

Comments
 (0)