{"record":{"id":"ff152f601f21cfb5","repo":"iflytek/astron-agent","slug":"protocol-build-error","errorCode":"PROTOCOL_BUILD_ERROR","errorMessage":"Node {node_id} does not exist","messagePattern":"Node (.+?) does not exist","errorType":"error_code","errorClass":"CustomException","httpStatus":null,"severity":"error","filePath":"core/workflow/engine/entities/workflow_dsl.py","lineNumber":161,"sourceCode":"\n    # Node information\n    nodes: List[Node]\n\n    # Edge information\n    edges: List[Edge]\n\n    def check_nodes_exist(self, node_id: str) -> Node:\n        \"\"\"\n        Check if a node exists in the workflow.\n\n        :param node_id: ID of the node to check\n        :return: Node object if found\n        :raises CustomException: If node is not found\n        \"\"\"\n        for node in self.nodes:\n            if node.id == node_id:\n                return node\n        raise CustomException(\n            CodeEnum.PROTOCOL_BUILD_ERROR, err_msg=f\"Node {node_id} does not exist\"\n        )\n\n    def extract_iteration_sub_dsl(self, iteration_node_id: str) -> \"WorkflowDSL\":\n        \"\"\"\n        Extract the standalone DSL for an iteration subgraph.\n\n        :param iteration_node_id: The iteration container node ID\n        :return: WorkflowDSL containing only the iteration subgraph\n        :raises CustomException: If the iteration node or subgraph is invalid\n        \"\"\"\n        from workflow.engine.entities.chains import Chains\n\n        chains = Chains(workflow_schema=self)\n        chains.gen()\n\n        iteration_chains = chains.iteration_chains.get(iteration_node_id)\n        if iteration_chains is None:","sourceCodeStart":143,"sourceCodeEnd":179,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/workflow/engine/entities/workflow_dsl.py#L143-L179","documentation":"Raised by WorkflowDSL.check_nodes_exist when a node lookup by ID fails during DSL traversal/processing. The DSL is treated as a protocol document; a reference to a node ID that is absent from the node list means the workflow graph is malformed, so a PROTOCOL_BUILD_ERROR is thrown instead of returning null.","triggerScenarios":"Calling check_nodes_exist (or any code path that resolves node IDs, e.g. edge/variable resolution) with a node_id that is not present in self.nodes — typically a deleted node still referenced by an edge, variable reference, or branch target.","commonSituations":"Hand-edited or legacy DSL JSON where a node was removed but edges still point to it; importing a workflow exported from a different version where node IDs were regenerated; frontend sending stale node IDs after undo/delete.","solutions":["Open the workflow in the console editor and remove/repair edges or variable references that point to the missing node","Validate the DSL before execution: collect all referenced node IDs (edges, branches, variable sources) and diff against the node list","Re-export/re-save the workflow so IDs are regenerated consistently","Check for version skew between the saved DSL and the running engine version"],"exampleFix":"// before: engine fails at runtime\nengine.run(dsl)\n// after: validate referenced nodes first\nnode_ids = {e.source_id for e in dsl.edges} | {e.target_id for e in dsl.edges}\nmissing = node_ids - {n.id for n in dsl.nodes}\nif missing:\n    raise ValueError(f\"DSL references missing nodes: {missing}\")\nengine.run(dsl)","handlingStrategy":"validation","validationCode":"const nodeIds = new Set(dsl.nodes.map(n => n.id));\nconst refs = [...dsl.edges.flatMap(e => [e.source_id, e.target_id])];\nconst missing = refs.filter(id => !nodeIds.has(id));\nif (missing.length) throw new Error(`DSL references missing nodes: ${missing}`);","typeGuard":"function nodeExists(dsl, id) {\n  return dsl.nodes.some(n => n.id === id);\n}","tryCatchPattern":"try {\n  dsl.check_nodes_exist(node_id)\n} catch (CustomException e) when (e.code == PROTOCOL_BUILD_ERROR) {\n  logger.error(`broken DSL reference: ${node_id}`);\n  throw new WorkflowValidationError(e);\n}","preventionTips":["Validate DSL integrity (all edge endpoints exist as nodes) before save and before run","Block publishing workflows with dangling references in the editor","Regenerate/normalize node IDs on import instead of trusting foreign IDs","Add a DSL schema/migration check on version upgrades"],"tags":["workflow","dsl","graph"],"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"}