diff --git a/api/dify_graph/nodes/loop/loop_node.py b/api/dify_graph/nodes/loop/loop_node.py index a2d827f034..363f902f82 100644 --- a/api/dify_graph/nodes/loop/loop_node.py +++ b/api/dify_graph/nodes/loop/loop_node.py @@ -406,11 +406,12 @@ class LoopNode(LLMUsageTrackingMixin, Node[LoopNodeData]): SegmentType.ARRAY_OBJECT, SegmentType.ARRAY_STRING, ]: - if original_value and isinstance(original_value, str): - value = json.loads(original_value) + # New typed payloads may already provide native lists, while legacy + # configs still serialize array constants as JSON strings. + if isinstance(original_value, str): + value = json.loads(original_value) if original_value else [] else: - logger.warning("unexpected value for LoopNode, value_type=%s, value=%s", original_value, var_type) - value = [] + value = original_value else: raise AssertionError("this statement should be unreachable.") try: diff --git a/api/tests/unit_tests/core/workflow/nodes/test_loop_node.py b/api/tests/unit_tests/core/workflow/nodes/test_loop_node.py index 6372583839..b3904fe707 100644 --- a/api/tests/unit_tests/core/workflow/nodes/test_loop_node.py +++ b/api/tests/unit_tests/core/workflow/nodes/test_loop_node.py @@ -1,6 +1,9 @@ +import pytest + from dify_graph.entities.graph_config import NodeConfigDictAdapter -from dify_graph.nodes.loop.entities import LoopNodeData +from dify_graph.nodes.loop.entities import LoopNodeData, LoopValue from dify_graph.nodes.loop.loop_node import LoopNode +from dify_graph.variables.types import SegmentType def test_extract_variable_selector_to_variable_mapping_validates_child_node_configs(monkeypatch) -> None: @@ -50,3 +53,21 @@ def test_extract_variable_selector_to_variable_mapping_validates_child_node_conf ) assert seen_configs == [child_node_config] + + +@pytest.mark.parametrize( + ("var_type", "original_value", "expected_value"), + [ + (SegmentType.ARRAY_STRING, ["alpha", "beta"], ["alpha", "beta"]), + (SegmentType.ARRAY_NUMBER, [1, 2.5], [1, 2.5]), + (SegmentType.ARRAY_OBJECT, [{"name": "item"}], [{"name": "item"}]), + (SegmentType.ARRAY_STRING, '["legacy", "json"]', ["legacy", "json"]), + ], +) +def test_get_segment_for_constant_accepts_native_array_values( + var_type: SegmentType, original_value: LoopValue, expected_value: LoopValue +) -> None: + segment = LoopNode._get_segment_for_constant(var_type, original_value) + + assert segment.value_type == var_type + assert segment.value == expected_value