iflytek/astron-agent · error · ValueError

node is not exist

Error message

{source_node_id} node is not exist

What it means

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.

Solutions

  1. Ensure the iteration node with that id exists in the DSL nodes map before/alongside the edge
  2. Remove stale edges attached to deleted iteration nodes
  3. Re-save the workflow in the editor to regenerate consistent edges
  4. Catch ValueError in tooling that programmatically edits DSLs and repair dangling edges

Example fix

# before: edge exists, node removed
{"edges": [{"source": "iteration::abc"}], "nodes": []}
# after: keep node and edge consistent
{"edges": [{"source": "iteration::abc"}], "nodes": [{"id": "iteration::abc"}]}
Defensive patterns

Strategy: validation

Validate before calling

def check_iteration_edges(dsl):
    ids = {n["id"] for n in dsl["nodes"]}
    for e in dsl["edges"]:
        if e["source"].startswith("iteration::") and e["source"] not in ids:
            raise ValueError(f"missing iteration node {e['source']}")

Type guard

def iteration_node_exists(node_dict, source_id):
    return source_id.startswith("iteration::") and source_id in node_dict

Try / catch

try:
    chains = Chains.build(dsl)
except ValueError as e:
    if "node is not exist" in str(e):
        # remove/repair the dangling iteration edge before rebuilding
        ...
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of iflytek/astron-agent@5e758547a8 (2026-09-12). Data as JSON: /api/errors/85f6a47e5884c6e9. Report an issue: GitHub.

Appendix: source

Thrown at core/workflow/engine/entities/chains.py:215

            return target_node_id
        return current_end_node_id

    def _record_iteration_start(
        self,
        iteration_dict: Dict[str, str],
        node_dict: Dict[str, Node],
        source_node_id: str,
    ) -> None:
        """
        Record the start node configured for an iteration node.
        """
        source_node_id_prefix = source_node_id.split("::")[0]
        if source_node_id_prefix != NodeType.ITERATION.value:
            return

        iter_node: Node | None = node_dict.get(source_node_id)
        if iter_node is None:
            raise ValueError(f"{source_node_id} node is not exist")

        start_id = iter_node.data.nodeParam.get("IterationStartNodeId")
        iteration_dict[source_node_id] = str(start_id or "")

    def _record_loop_start(
        self,
        loop_dict: Dict[str, str],
        node_dict: Dict[str, Node],
        source_node_id: str,
    ) -> None:
        """
        Record the start node configured for a loop node.
        """
        source_node_id_prefix = source_node_id.split("::")[0]
        if source_node_id_prefix != NodeType.LOOP.value:
            return

        loop_node: Node | None = node_dict.get(source_node_id)

View on GitHub (pinned to 5e758547a8)