{"record":{"id":"85f6a47e5884c6e9","repo":"iflytek/astron-agent","slug":"source-node-id-node-is-not-exist","errorCode":null,"errorMessage":"{source_node_id} node is not exist","messagePattern":"(.+?) node is not exist","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"core/workflow/engine/entities/chains.py","lineNumber":215,"sourceCode":"            return target_node_id\n        return current_end_node_id\n\n    def _record_iteration_start(\n        self,\n        iteration_dict: Dict[str, str],\n        node_dict: Dict[str, Node],\n        source_node_id: str,\n    ) -> None:\n        \"\"\"\n        Record the start node configured for an iteration node.\n        \"\"\"\n        source_node_id_prefix = source_node_id.split(\"::\")[0]\n        if source_node_id_prefix != NodeType.ITERATION.value:\n            return\n\n        iter_node: Node | None = node_dict.get(source_node_id)\n        if iter_node is None:\n            raise ValueError(f\"{source_node_id} node is not exist\")\n\n        start_id = iter_node.data.nodeParam.get(\"IterationStartNodeId\")\n        iteration_dict[source_node_id] = str(start_id or \"\")\n\n    def _record_loop_start(\n        self,\n        loop_dict: Dict[str, str],\n        node_dict: Dict[str, Node],\n        source_node_id: str,\n    ) -> None:\n        \"\"\"\n        Record the start node configured for a loop node.\n        \"\"\"\n        source_node_id_prefix = source_node_id.split(\"::\")[0]\n        if source_node_id_prefix != NodeType.LOOP.value:\n            return\n\n        loop_node: Node | None = node_dict.get(source_node_id)","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/engine/entities/chains.py#L197-L233","documentation":"Chains._record_iteration_start looks up the iteration node for an incoming edge in the node dict and raises ValueError when the source node id (an ITERATION node, by prefix) is missing. This happens while Chains processes edges via _deal_edges to record which node starts an iteration. Unlike CustomException paths this is a plain ValueError, so it surfaces as an unexpected internal failure rather than a structured workflow error.","triggerScenarios":"An edge whose source id has the 'iteration' prefix (e.g. 'iteration::<id>') but the corresponding node is not present in node_dict — dangling edge into/out of an iteration node after the node was deleted or the DSL was hand-edited.","commonSituations":"Deleting an iteration node in the editor while its edges persist; merging workflow versions where the iteration node id changed; importing partial DSLs that contain edges but not the iteration node definition.","solutions":["Ensure the iteration node with that id exists in the DSL nodes map before/alongside the edge","Remove stale edges attached to deleted iteration nodes","Re-save the workflow in the editor to regenerate consistent edges","Catch ValueError in tooling that programmatically edits DSLs and repair dangling edges"],"exampleFix":"# before: edge exists, node removed\n{\"edges\": [{\"source\": \"iteration::abc\"}], \"nodes\": []}\n# after: keep node and edge consistent\n{\"edges\": [{\"source\": \"iteration::abc\"}], \"nodes\": [{\"id\": \"iteration::abc\"}]}","handlingStrategy":"validation","validationCode":"def check_iteration_edges(dsl):\n    ids = {n[\"id\"] for n in dsl[\"nodes\"]}\n    for e in dsl[\"edges\"]:\n        if e[\"source\"].startswith(\"iteration::\") and e[\"source\"] not in ids:\n            raise ValueError(f\"missing iteration node {e['source']}\")","typeGuard":"def iteration_node_exists(node_dict, source_id):\n    return source_id.startswith(\"iteration::\") and source_id in node_dict","tryCatchPattern":"try:\n    chains = Chains.build(dsl)\nexcept ValueError as e:\n    if \"node is not exist\" in str(e):\n        # remove/repair the dangling iteration edge before rebuilding\n        ...\n    raise","preventionTips":["Delete edges together with their iteration nodes when editing DSLs programmatically","Re-export workflows from the editor after structural edits","Diff node ids across workflow versions before merging"],"tags":["workflow","iteration","dangling-edge"],"backgroundTag":"entity-not-found","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}