Debug and preview run error in parallel workflow #5768

Closed
opened 2026-02-21 18:12:30 -05:00 by yindo · 3 comments
Owner

Originally created by @zhijianma on GitHub (Sep 23, 2024).

Self Checks

  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • [FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

0.8.3

Cloud or Self Hosted

Cloud

Steps to reproduce

image

The following is the workflow config

代码执行(Code)
arg1: sys.query

def main(arg1: str) -> dict:
    return {
        "result": arg1
    }

代码执行2 (Code2)
arg1: sys.query

def main(arg1: str) -> dict:
    import time
    time.sleep(10)
    return {
        "result": arg1,
    }

代码执行3(Code3)
arg1: sys.query


def main(arg1: str) -> dict:
    import time
    time.sleep(5)
    return {
        "result": arg1,
    }

代码执行4(Code4)
arg1: 代码执行2.result
arg2: 代码执行3.result

def main(arg1: str, arg2: str) -> dict:
    import time
    time.sleep(5)
    return {
        "result": arg1 + arg2,
    }

代码执行5(Code5)
arg1: 代码执行.result
arg2: 代码执行4.result

def main(arg1: str, arg2: str) -> dict:
    return {
        "result": arg1 + arg2,
    }

✔️ Expected Behavior

Node 代码执行4 needs to wait for its predecessor nodes to complete before executing.

Actual Behavior

Node 代码执行4 gets a None value from args1.

Traceback (most recent call last): File "/var/sandbox/sandbox-python/tmp/df08b01c_e944_4b0b_9424_e7c2745ced23.py", line 48, in File "", line 19, in File "", line 8, in main TypeError: unsupported operand type(s) for +: 'NoneType' and 'str' error: exit status 255

Originally created by @zhijianma on GitHub (Sep 23, 2024). ### Self Checks - [X] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [X] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [X] I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). - [X] [FOR CHINESE USERS] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:) - [X] Please do not modify this template :) and fill in all the required fields. ### Dify version 0.8.3 ### Cloud or Self Hosted Cloud ### Steps to reproduce ![image](https://github.com/user-attachments/assets/60cd01a0-80ac-4216-9a84-4a32133113ba) The following is the workflow config 代码执行(Code) arg1: sys.query ```python def main(arg1: str) -> dict: return { "result": arg1 } ``` 代码执行2 (Code2) arg1: sys.query ```python def main(arg1: str) -> dict: import time time.sleep(10) return { "result": arg1, } ``` 代码执行3(Code3) arg1: sys.query ```python def main(arg1: str) -> dict: import time time.sleep(5) return { "result": arg1, } ``` 代码执行4(Code4) arg1: 代码执行2.result arg2: 代码执行3.result ```python def main(arg1: str, arg2: str) -> dict: import time time.sleep(5) return { "result": arg1 + arg2, } ``` 代码执行5(Code5) arg1: 代码执行.result arg2: 代码执行4.result ```python def main(arg1: str, arg2: str) -> dict: return { "result": arg1 + arg2, } ``` ### ✔️ Expected Behavior Node `代码执行4` needs to wait for its predecessor nodes to complete before executing. ### ❌ Actual Behavior Node `代码执行4` gets a `None` value from args1. Traceback (most recent call last): File "/var/sandbox/sandbox-python/tmp/df08b01c_e944_4b0b_9424_e7c2745ced23.py", line 48, in <module> File "<string>", line 19, in <module> File "<string>", line 8, in main TypeError: unsupported operand type(s) for +: 'NoneType' and 'str' error: exit status 255
yindo added the 🐞 bug label 2026-02-21 18:12:30 -05:00
yindo closed this issue 2026-02-21 18:12:30 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 23, 2024):

@zhijianma Hello! I'm here to help you with any bugs, questions, or contributions. Let's tackle this together while waiting for a human maintainer.

To resolve the TypeError in 代码执行4 where it receives a None value for arg1 in a parallel workflow, you need to ensure that arg1 is not None before processing it. You can add a check at the beginning of the function to handle the case where arg1 is None.

Here is the modified code for 代码执行4:

def main(arg1: str, arg2: str) -> dict:
    if arg1 is None or arg2 is None:
        return {
            "result": "Error: One or both arguments are None"
        }
    
    import time
    time.sleep(5)
    return {
        "result": arg1 + arg2,
    }

Additionally, ensure that the variable pool in your workflow is correctly set up to provide the necessary inputs. For example, in the test case provided, the variable pool is constructed and populated with values for args1 and args2:

variable_pool = VariablePool(
    system_variables={SystemVariableKey.FILES: [], SystemVariableKey.USER_ID: "aaa"},
    user_inputs={},
    environment_variables=[],
    conversation_variables=[],
)
variable_pool.add(["1", "123", "args1"], 1)
variable_pool.add(["1", "123", "args2"], 3)

Make sure that your workflow's variable pool is similarly configured to avoid None values for arg1 [1][2].

Regarding the execution order, Dify handles dependencies between nodes in a parallel workflow by ensuring that all nodes within the parallel structure operate independently and execute tasks concurrently. Each parallel node is triggered simultaneously by the preceding node, and they do not wait for each other to complete [3].

To continue talking to Dosu, mention @dosu.

@dosubot[bot] commented on GitHub (Sep 23, 2024): <!-- Greeting --> @zhijianma Hello! I'm here to help you with any bugs, questions, or contributions. Let's tackle this together while waiting for a human maintainer. <!-- Answer --> To resolve the `TypeError` in `代码执行4` where it receives a `None` value for `arg1` in a parallel workflow, you need to ensure that `arg1` is not `None` before processing it. You can add a check at the beginning of the function to handle the case where `arg1` is `None`. Here is the modified code for `代码执行4`: ```python def main(arg1: str, arg2: str) -> dict: if arg1 is None or arg2 is None: return { "result": "Error: One or both arguments are None" } import time time.sleep(5) return { "result": arg1 + arg2, } ``` Additionally, ensure that the variable pool in your workflow is correctly set up to provide the necessary inputs. For example, in the test case provided, the variable pool is constructed and populated with values for `args1` and `args2`: ```python variable_pool = VariablePool( system_variables={SystemVariableKey.FILES: [], SystemVariableKey.USER_ID: "aaa"}, user_inputs={}, environment_variables=[], conversation_variables=[], ) variable_pool.add(["1", "123", "args1"], 1) variable_pool.add(["1", "123", "args2"], 3) ``` Make sure that your workflow's variable pool is similarly configured to avoid `None` values for `arg1` <sup>[[1]](https://github.com/langgenius/dify-docs/blob/main/zh_CN/guides/workflow/node/variable-assignment.md)</sup><sup>[[2]](https://github.com/langgenius/dify/blob/main/api/tests/integration_tests/workflow/nodes/test_template_transform.py)</sup>. Regarding the execution order, Dify handles dependencies between nodes in a parallel workflow by ensuring that all nodes within the parallel structure operate independently and execute tasks concurrently. Each parallel node is triggered simultaneously by the preceding node, and they do not wait for each other to complete <sup>[[3]](https://github.com/langgenius/dify-docs/blob/main/en/guides/workflow/orchestrate-node.md)</sup>. <!-- Dosu Comment Footer --> *To continue talking to [Dosu](https://dosu.dev), mention @dosu.*
Author
Owner

@crazywoola commented on GitHub (Sep 24, 2024):

Please attach the DSL.
And I am not sure why do you need to code like this, I think a single code node is enough for the whole task and it won't generate errors.

@crazywoola commented on GitHub (Sep 24, 2024): Please attach the DSL. And I am not sure why do you need to code like this, I think a single code node is enough for the whole task and it won't generate errors.
Author
Owner

@zhijianma commented on GitHub (Sep 24, 2024):

Please attach the DSL. And I am not sure why do you need to code like this, I think a single code node is enough for the whole task and it won't generate errors.

In this case, I just use Code to simulate a parallel mode for a multi-input scenario.
And the DSL file as follows:

app:
  description: ffd
  icon: 🤖
  icon_background: '#FFEAD5'
  mode: workflow
  name: test_workflow
  use_icon_as_answer_icon: false
kind: app
version: 0.1.2
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      image:
        enabled: false
        number_limits: 3
        transfer_methods:
        - local_file
        - remote_url
    opening_statement: ''
    retriever_resource:
      enabled: true
    sensitive_word_avoidance:
      enabled: false
    speech_to_text:
      enabled: false
    suggested_questions: []
    suggested_questions_after_answer:
      enabled: false
    text_to_speech:
      enabled: false
      language: ''
      voice: ''
  graph:
    edges:
    - data:
        isInIteration: false
        sourceType: start
        targetType: code
      id: 1725590432628-source-1727072856489-target
      selected: false
      source: '1725590432628'
      sourceHandle: source
      target: '1727072856489'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: start
        targetType: code
      id: 1725590432628-source-1727147018481-target
      selected: false
      source: '1725590432628'
      sourceHandle: source
      target: '1727147018481'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: start
        targetType: code
      id: 1725590432628-source-1727147052531-target
      selected: false
      source: '1725590432628'
      sourceHandle: source
      target: '1727147052531'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: code
        targetType: code
      id: 1727147018481-source-1727147066015-target
      selected: false
      source: '1727147018481'
      sourceHandle: source
      target: '1727147066015'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: code
        targetType: code
      id: 1727147052531-source-1727147066015-target
      selected: false
      source: '1727147052531'
      sourceHandle: source
      target: '1727147066015'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: code
        targetType: code
      id: 1727072856489-source-1727147079381-target
      selected: false
      source: '1727072856489'
      sourceHandle: source
      target: '1727147079381'
      targetHandle: target
      type: custom
      zIndex: 0
    - data:
        isInIteration: false
        sourceType: code
        targetType: code
      id: 1727147066015-source-1727147079381-target
      selected: false
      source: '1727147066015'
      sourceHandle: source
      target: '1727147079381'
      targetHandle: target
      type: custom
      zIndex: 0
    nodes:
    - data:
        desc: ''
        selected: false
        title: 开始
        type: start
        variables:
        - label: query
          max_length: 48
          options: []
          required: true
          type: text-input
          variable: query
      height: 90
      id: '1725590432628'
      position:
        x: 38.56889643898978
        y: 313.8700796623155
      positionAbsolute:
        x: 38.56889643898978
        y: 313.8700796623155
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        code: "\ndef main(arg1: str) -> dict:\n    return {\n        \"result\": arg1\n\
          \    }\n"
        code_language: python3
        desc: ''
        outputs:
          result:
            children: null
            type: string
        selected: false
        title: 代码执行
        type: code
        variables:
        - value_selector:
          - '1725590432628'
          - query
          variable: arg1
      height: 54
      id: '1727072856489'
      position:
        x: 348.94291237145285
        y: 328.2116155103575
      positionAbsolute:
        x: 348.94291237145285
        y: 328.2116155103575
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        code: "\ndef main(arg1: str) -> dict:\n    import time\n    time.sleep(10)\n\
          \    return {\n        \"result\": arg1,\n    }\n"
        code_language: python3
        desc: ''
        outputs:
          result:
            children: null
            type: string
        selected: false
        title: 代码执行 2
        type: code
        variables:
        - value_selector:
          - '1725590432628'
          - query
          variable: arg1
      height: 54
      id: '1727147018481'
      position:
        x: 348.94291237145285
        y: 481.764766868757
      positionAbsolute:
        x: 348.94291237145285
        y: 481.764766868757
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        code: "\ndef main(arg1: str) -> dict:\n    import time\n    time.sleep(5)\n\
          \    return {\n        \"result\": arg1,\n    }\n"
        code_language: python3
        desc: ''
        outputs:
          result:
            children: null
            type: string
        selected: false
        title: 代码执行 3
        type: code
        variables:
        - value_selector:
          - '1725590432628'
          - query
          variable: arg1
      height: 54
      id: '1727147052531'
      position:
        x: 348.94291237145285
        y: 574.7647668687571
      positionAbsolute:
        x: 348.94291237145285
        y: 574.7647668687571
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        code: "\ndef main(arg1: str, arg2: str) -> dict:\n    import time\n    time.sleep(5)\n\
          \    return {\n        \"result\": arg1 + arg2,\n    }\n"
        code_language: python3
        desc: ''
        outputs:
          result:
            children: null
            type: string
        selected: false
        title: 代码执行 4
        type: code
        variables:
        - value_selector:
          - '1727147018481'
          - result
          variable: arg1
        - value_selector:
          - '1727147052531'
          - result
          variable: arg2
      height: 54
      id: '1727147066015'
      position:
        x: 694.374015932463
        y: 516.8218544973042
      positionAbsolute:
        x: 694.374015932463
        y: 516.8218544973042
      selected: true
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    - data:
        code: "\ndef main(arg1: str, arg2: str) -> dict:\n    return {\n        \"\
          result\": arg1 + arg2,\n    }\n"
        code_language: python3
        desc: ''
        outputs:
          result:
            children: null
            type: string
        selected: false
        title: 代码执行 5
        type: code
        variables:
        - value_selector:
          - '1727072856489'
          - result
          variable: arg1
        - value_selector:
          - '1727147066015'
          - result
          variable: arg2
      height: 54
      id: '1727147079381'
      position:
        x: 949.3561132228729
        y: 328.2116155103575
      positionAbsolute:
        x: 949.3561132228729
        y: 328.2116155103575
      selected: false
      sourcePosition: right
      targetPosition: left
      type: custom
      width: 244
    viewport:
      x: 640.8622190234412
      y: 215.12657776416864
      zoom: 0.5109640591636222

@zhijianma commented on GitHub (Sep 24, 2024): > Please attach the DSL. And I am not sure why do you need to code like this, I think a single code node is enough for the whole task and it won't generate errors. In this case, I just use `Code` to simulate a parallel mode for a multi-input scenario. And the DSL file as follows: ```yaml app: description: ffd icon: 🤖 icon_background: '#FFEAD5' mode: workflow name: test_workflow use_icon_as_answer_icon: false kind: app version: 0.1.2 workflow: conversation_variables: [] environment_variables: [] features: file_upload: image: enabled: false number_limits: 3 transfer_methods: - local_file - remote_url opening_statement: '' retriever_resource: enabled: true sensitive_word_avoidance: enabled: false speech_to_text: enabled: false suggested_questions: [] suggested_questions_after_answer: enabled: false text_to_speech: enabled: false language: '' voice: '' graph: edges: - data: isInIteration: false sourceType: start targetType: code id: 1725590432628-source-1727072856489-target selected: false source: '1725590432628' sourceHandle: source target: '1727072856489' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false sourceType: start targetType: code id: 1725590432628-source-1727147018481-target selected: false source: '1725590432628' sourceHandle: source target: '1727147018481' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false sourceType: start targetType: code id: 1725590432628-source-1727147052531-target selected: false source: '1725590432628' sourceHandle: source target: '1727147052531' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false sourceType: code targetType: code id: 1727147018481-source-1727147066015-target selected: false source: '1727147018481' sourceHandle: source target: '1727147066015' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false sourceType: code targetType: code id: 1727147052531-source-1727147066015-target selected: false source: '1727147052531' sourceHandle: source target: '1727147066015' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false sourceType: code targetType: code id: 1727072856489-source-1727147079381-target selected: false source: '1727072856489' sourceHandle: source target: '1727147079381' targetHandle: target type: custom zIndex: 0 - data: isInIteration: false sourceType: code targetType: code id: 1727147066015-source-1727147079381-target selected: false source: '1727147066015' sourceHandle: source target: '1727147079381' targetHandle: target type: custom zIndex: 0 nodes: - data: desc: '' selected: false title: 开始 type: start variables: - label: query max_length: 48 options: [] required: true type: text-input variable: query height: 90 id: '1725590432628' position: x: 38.56889643898978 y: 313.8700796623155 positionAbsolute: x: 38.56889643898978 y: 313.8700796623155 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: code: "\ndef main(arg1: str) -> dict:\n return {\n \"result\": arg1\n\ \ }\n" code_language: python3 desc: '' outputs: result: children: null type: string selected: false title: 代码执行 type: code variables: - value_selector: - '1725590432628' - query variable: arg1 height: 54 id: '1727072856489' position: x: 348.94291237145285 y: 328.2116155103575 positionAbsolute: x: 348.94291237145285 y: 328.2116155103575 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: code: "\ndef main(arg1: str) -> dict:\n import time\n time.sleep(10)\n\ \ return {\n \"result\": arg1,\n }\n" code_language: python3 desc: '' outputs: result: children: null type: string selected: false title: 代码执行 2 type: code variables: - value_selector: - '1725590432628' - query variable: arg1 height: 54 id: '1727147018481' position: x: 348.94291237145285 y: 481.764766868757 positionAbsolute: x: 348.94291237145285 y: 481.764766868757 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: code: "\ndef main(arg1: str) -> dict:\n import time\n time.sleep(5)\n\ \ return {\n \"result\": arg1,\n }\n" code_language: python3 desc: '' outputs: result: children: null type: string selected: false title: 代码执行 3 type: code variables: - value_selector: - '1725590432628' - query variable: arg1 height: 54 id: '1727147052531' position: x: 348.94291237145285 y: 574.7647668687571 positionAbsolute: x: 348.94291237145285 y: 574.7647668687571 selected: false sourcePosition: right targetPosition: left type: custom width: 244 - data: code: "\ndef main(arg1: str, arg2: str) -> dict:\n import time\n time.sleep(5)\n\ \ return {\n \"result\": arg1 + arg2,\n }\n" code_language: python3 desc: '' outputs: result: children: null type: string selected: false title: 代码执行 4 type: code variables: - value_selector: - '1727147018481' - result variable: arg1 - value_selector: - '1727147052531' - result variable: arg2 height: 54 id: '1727147066015' position: x: 694.374015932463 y: 516.8218544973042 positionAbsolute: x: 694.374015932463 y: 516.8218544973042 selected: true sourcePosition: right targetPosition: left type: custom width: 244 - data: code: "\ndef main(arg1: str, arg2: str) -> dict:\n return {\n \"\ result\": arg1 + arg2,\n }\n" code_language: python3 desc: '' outputs: result: children: null type: string selected: false title: 代码执行 5 type: code variables: - value_selector: - '1727072856489' - result variable: arg1 - value_selector: - '1727147066015' - result variable: arg2 height: 54 id: '1727147079381' position: x: 949.3561132228729 y: 328.2116155103575 positionAbsolute: x: 949.3561132228729 y: 328.2116155103575 selected: false sourcePosition: right targetPosition: left type: custom width: 244 viewport: x: 640.8622190234412 y: 215.12657776416864 zoom: 0.5109640591636222 ```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#5768