{"record":{"id":"e24f37ec7aa3e2d6","repo":"deepset-ai/haystack","slug":"connection-must-have-both-sender-and-receiver-s","errorCode":null,"errorMessage":"Connection must have both sender and receiver: ${sender_repr} -> ${receiver_repr}","messagePattern":"Connection must have both sender and receiver: (.+?) -> (.+?)","errorType":"exception","errorClass":"PipelineConnectError","httpStatus":null,"severity":"error","filePath":"haystack/core/pipeline/base.py","lineNumber":757,"sourceCode":"\n            # Get the only possible match\n            sender_socket = name_matches[0][0]\n            receiver_socket = name_matches[0][1]\n            conversion_strategy = name_matches[0][2]\n\n        # Connection must be valid on both sender/receiver sides\n        if not sender_socket or not receiver_socket or not sender_component_name or not receiver_component_name:\n            if sender_component_name and sender_socket:\n                sender_repr = f\"{sender_component_name}.{sender_socket.name} ({_type_name(sender_socket.type)})\"\n            else:\n                sender_repr = \"input needed\"\n\n            if receiver_component_name and receiver_socket:\n                receiver_repr = f\"({_type_name(receiver_socket.type)}) {receiver_component_name}.{receiver_socket.name}\"\n            else:\n                receiver_repr = \"output\"\n            msg = f\"Connection must have both sender and receiver: {sender_repr} -> {receiver_repr}\"\n            raise PipelineConnectError(msg)\n\n        logger.debug(\n            \"Connecting '{sender_component}.{sender_socket_name}' to '{receiver_component}.{receiver_socket_name}'\",\n            sender_component=sender_component_name,\n            sender_socket_name=sender_socket.name,\n            receiver_component=receiver_component_name,\n            receiver_socket_name=receiver_socket.name,\n        )\n\n        if receiver_component_name in sender_socket.receivers and sender_component_name in receiver_socket.senders:\n            # This is already connected, nothing to do\n            return self\n\n        if receiver_socket.senders:\n            receiver_socket = self._make_socket_auto_variadic(\n                component_name=receiver_component_name, receiver_socket=receiver_socket, error_type=PipelineConnectError\n            )\n","sourceCodeStart":739,"sourceCodeEnd":775,"githubUrl":"https://github.com/deepset-ai/haystack/blob/e318778c9bf60a1963e3b5f451359655dd696c30/haystack/core/pipeline/base.py#L739-L775","documentation":"Pipeline.connect() raises PipelineConnectError when only one side of the connection could be resolved — i.e. the sender or receiver portion resolves to 'input'/'output' but not both components with sockets. A valid connection needs both a resolved sender (component+socket) and a resolved receiver (component+socket).","triggerScenarios":"Using the legacy 'component.socket' shorthand with 'input'/'output' literals such as pipeline.connect('comp.input', 'output') or similar partial notations that resolve only one side, in a haystack version that still accepts the input/output keyword forms but finds the other side missing.","commonSituations":"Mixing old deepset-ai/haystack 1.x pipeline.connect('a', 'b.c') conventions with 2.x semantics; passing 'input'/'output' placeholder strings copied from old code or docs; partially commenting out one side of a connection.","solutions":["Provide full 'component.socket' names for BOTH sender and receiver so both sides resolve","Remove any literal 'input'/'output' placeholders copied from 1.x pipelines","Verify both component names and socket names exist on their components"],"exampleFix":"// before\npipeline.connect('retriever', 'output')\n// after\npipeline.connect('retriever.documents', 'writer.documents')","handlingStrategy":"validation","validationCode":"parts_s, parts_r = sender_spec.split('.'), receiver_spec.split('.')\nassert all(len(p) == 2 and p[0] not in ('input', 'output') for p in (parts_s, parts_r)), 'Provide full component.socket names for both sides'","typeGuard":"def is_full_socket_spec(spec: str) -> bool:\n    comp, _, sock = spec.partition('.')\n    return bool(comp and sock) and comp not in ('input', 'output')","tryCatchPattern":"try:\n    pipeline.connect(sender_spec, receiver_spec)\nexcept PipelineConnectError as e:\n    if 'must have both sender and receiver' in str(e):\n        raise ValueError('Use full component.socket notation on both sides') from e","preventionTips":["Avoid 1.x 'input'/'output' endpoint conventions in 2.x pipelines","Always use component.socket on both sides when partially specifying","Migrate legacy pipeline definitions systematically"],"tags":["pipeline","haystack","connection","partial-resolution"],"backgroundTag":"ambiguous-connection","analyzedSha":"e318778c9bf60a1963e3b5f451359655dd696c30","analyzedAt":"2026-08-30T11:45:20.711Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}