{"record":{"id":"9eca02a55eeddd92","repo":"infiniflow/ragflow","slug":"switch-to-can-not-be-empty","errorCode":null,"errorMessage":"[Switch] 'To' can not be empty!","messagePattern":"\\[Switch\\] 'To' can not be empty!","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/component/switch.py","lineNumber":49,"sourceCode":"        super().__init__()\n        \"\"\"\n        {\n            \"logical_operator\" : \"and | or\"\n            \"items\" : [\n                            {\"cpn_id\": \"categorize:0\", \"operator\": \"contains\", \"value\": \"\"},\n                            {\"cpn_id\": \"categorize:0\", \"operator\": \"contains\", \"value\": \"\"},...],\n            \"to\": \"\"\n        }\n        \"\"\"\n        self.conditions = []\n        self.end_cpn_ids = []\n        self.operators = [\"contains\", \"not contains\", \"start with\", \"end with\", \"empty\", \"not empty\", \"=\", \"≠\", \">\", \"<\", \"≥\", \"≤\"]\n\n    def check(self):\n        self.check_empty(self.conditions, \"[Switch] conditions\")\n        for cond in self.conditions:\n            if not cond[\"to\"]:\n                raise ValueError(\"[Switch] 'To' can not be empty!\")\n        self.check_empty(self.end_cpn_ids, \"[Switch] the ELSE/Other destination can not be empty.\")\n\n    def get_input_form(self) -> dict[str, dict]:\n        return {\"urls\": {\"name\": \"URLs\", \"type\": \"line\"}}\n\n\nclass Switch(ComponentBase, ABC):\n    component_name = \"Switch\"\n\n    @timeout(int(os.environ.get(\"COMPONENT_EXEC_TIMEOUT\", 3)))\n    def _invoke(self, **kwargs):\n        if self.check_if_canceled(\"Switch processing\"):\n            return\n\n        for cond in self._param.conditions:\n            if self.check_if_canceled(\"Switch processing\"):\n                return\n","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/agent/component/switch.py#L31-L67","documentation":"ValueError from SwitchParam.check(), raised during canvas validation before execution. Every condition in the Switch component must have a non-empty 'to' field naming the destination component for that branch; an empty destination makes the branch unroutable.","triggerScenarios":"A Switch condition created in the canvas but with its 'To' target not yet selected; the target component deleted after the condition was configured, leaving an empty string; hand-edited DSL with \"to\": \"\".","commonSituations":"Building a Switch and testing before wiring all branches; refactoring the graph and removing a downstream component that conditions pointed to; importing a template whose component IDs don't match the local canvas.","solutions":["Open the Switch component and assign a target component for every condition branch.","Remove orphaned conditions whose downstream components were deleted.","Run canvas validation (check) before execution so this surfaces at save time, not run time."],"exampleFix":"// before\n{\"conditions\": [{\"cpn_id\": \"switch:0\", \"operator\": \"contains\", \"value\": \"yes\", \"to\": \"\"}]}\n\n// after\n{\"conditions\": [{\"cpn_id\": \"switch:0\", \"operator\": \"contains\", \"value\": \"yes\", \"to\": \"answer:1\"}]}","handlingStrategy":"validation","validationCode":"for cond in switch_param.conditions:\n    assert cond.get('to'), f'Switch condition missing destination: {cond}'","typeGuard":"def switch_condition_routable(cond: dict) -> bool:\n    return bool(cond.get('to'))","tryCatchPattern":"try:\n    switch_param.check()\nexcept ValueError as e:\n    if \"'To' can not be empty\" in str(e):\n        # wire the branch target or delete the condition\n        ...","preventionTips":["Wire every Switch branch to a target before saving.","After deleting downstream components, clean up Switch conditions that pointed at them.","Run canvas check() programmatically after structural edits."],"tags":["switch","routing","configuration","agent-canvas"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}