Malformed DSL Import Creates Broken App and Crashes /apps Page. #22011

Open
opened 2026-02-21 20:15:15 -05:00 by yindo · 6 comments
Owner

Originally created by @nht1206 on GitHub (Feb 1, 2026).

Self Checks

  • I have read the Contributing Guide and Language Policy.
  • 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, otherwise it will be closed.
  • 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

1.12.0

Cloud or Self Hosted

Self Hosted (Source)

Steps to reproduce

  1. Attemp to import an app using the following DSL YAML content:
app:
  description: ''
  icon: 🤖
  icon_background: '#FFEAD5'
  mode: workflow
  name: Test
  use_icon_as_answer_icon: false
dependencies: []
kind: app
version: 0.5.0
workflow:
  conversation_variables: []
  environment_variables: []
  features:
    file_upload:
      enabled: false
      number_limits: 3
    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
  graph:
    edges: []
    nodes:
    - data:
        title: User Input
        type: start
        variables: []
      id: '1769765767428'
      position:
        x: 80
        y: 282
      positionAbsolute:
        x: 80
        y: 282
      sourcePosition: right
      targetPosition: left
      type: custom
    - type: custom  # This node is missing 'id' and 'data' fields
    viewport:
      x: 0
      y: 0
      zoom: 1
  rag_pipeline_variables: []
  1. The import will fail with an error
  2. Navigate to the /apps page

✔️ Expected Behavior

  1. If it fails to import, no app should be created in the database
  2. The /apps page should remain functional even if some apps have issues

Actual Behavior

  1. The app is still imserted into the database despite the failure
  2. The /apps page crashes when trying to list apps, making it completely inaccessible
  3. The error occurs in workflow.py:360 in the walk_nodes() method

Error Logs

Error 1: During Import (but app still created)

2026-01-30 10:04:01,336 ERROR [app_dsl_service.py:326] 3b4f83761d Failed to import app
Traceback (most recent call last):
  File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 288, in import_app
    app = self._create_or_update_app(
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 525, in _create_or_update_app
    workflow_service.sync_draft_workflow(
  File "/home/rhys/nht1206/dify/api/services/workflow_service.py", line 246, in sync_draft_workflow
    app_draft_workflow_was_synced.send(app_model, synced_draft_workflow=workflow)
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/blinker/base.py", line 249, in send
    result = receiver(sender, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/events/event_handlers/sync_webhook_when_app_created.py", line 22, in handle
    WebhookService.sync_webhook_relationships(app, synced_draft_workflow)
  File "/home/rhys/nht1206/dify/api/services/trigger/webhook_service.py", line 832, in sync_webhook_relationships
    nodes_id_in_graph = [node_id for node_id, _ in workflow.walk_nodes(NodeType.TRIGGER_WEBHOOK)]
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 354, in walk_nodes
    yield from (
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 357, in <genexpr>
    if node["data"]["type"] == specific_node_type.value
       ~~~~^^^^^^^^
KeyError: 'data'

Error 2: When Accessing /apps Endpoint

2026-01-30 10:03:20,203 ERROR [app.py:875] 0ca8d8078e Exception on /console/api/apps [GET]
Traceback (most recent call last):
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 902, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/api.py", line 404, in wrapper
    resp = resource(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/views.py", line 110, in view
    return current_app.ensure_sync(self.dispatch_request)(**kwargs)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/resource.py", line 41, in dispatch_request
    resp = meth(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 220, in decorated
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/libs/login.py", line 80, in decorated_view
    return current_app.ensure_sync(func)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 37, in decorated
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 232, in decorated
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/app/app.py", line 246, in get
    for _, node_data in workflow.walk_nodes():
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in walk_nodes
    yield from ((node["id"], node["data"]) for node in graph_dict["nodes"])
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in <genexpr>
    yield from ((node["id"], node["data"]) for node in graph_dict["nodes"])
                 ~~~~^^^^^^
KeyError: 'id'
Originally created by @nht1206 on GitHub (Feb 1, 2026). ### Self Checks - [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542). - [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, otherwise it will be closed. - [x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :) - [x] Please do not modify this template :) and fill in all the required fields. ### Dify version 1.12.0 ### Cloud or Self Hosted Self Hosted (Source) ### Steps to reproduce 1. Attemp to import an app using the following DSL YAML content: ```yaml app: description: '' icon: 🤖 icon_background: '#FFEAD5' mode: workflow name: Test use_icon_as_answer_icon: false dependencies: [] kind: app version: 0.5.0 workflow: conversation_variables: [] environment_variables: [] features: file_upload: enabled: false number_limits: 3 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 graph: edges: [] nodes: - data: title: User Input type: start variables: [] id: '1769765767428' position: x: 80 y: 282 positionAbsolute: x: 80 y: 282 sourcePosition: right targetPosition: left type: custom - type: custom # This node is missing 'id' and 'data' fields viewport: x: 0 y: 0 zoom: 1 rag_pipeline_variables: [] ``` 3. The import will fail with an error 4. Navigate to the `/apps` page ### ✔️ Expected Behavior 1. If it fails to import, no app should be created in the database 2. The `/apps` page should remain functional even if some apps have issues ### ❌ Actual Behavior 1. The app is still imserted into the database despite the failure 2. The `/apps` page crashes when trying to list apps, making it completely inaccessible 3. The error occurs in `workflow.py:360` in the `walk_nodes()` method ## Error Logs ### Error 1: During Import (but app still created) ``` 2026-01-30 10:04:01,336 ERROR [app_dsl_service.py:326] 3b4f83761d Failed to import app Traceback (most recent call last): File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 288, in import_app app = self._create_or_update_app( ^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 525, in _create_or_update_app workflow_service.sync_draft_workflow( File "/home/rhys/nht1206/dify/api/services/workflow_service.py", line 246, in sync_draft_workflow app_draft_workflow_was_synced.send(app_model, synced_draft_workflow=workflow) File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/blinker/base.py", line 249, in send result = receiver(sender, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/events/event_handlers/sync_webhook_when_app_created.py", line 22, in handle WebhookService.sync_webhook_relationships(app, synced_draft_workflow) File "/home/rhys/nht1206/dify/api/services/trigger/webhook_service.py", line 832, in sync_webhook_relationships nodes_id_in_graph = [node_id for node_id, _ in workflow.walk_nodes(NodeType.TRIGGER_WEBHOOK)] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/models/workflow.py", line 354, in walk_nodes yield from ( File "/home/rhys/nht1206/dify/api/models/workflow.py", line 357, in <genexpr> if node["data"]["type"] == specific_node_type.value ~~~~^^^^^^^^ KeyError: 'data' ``` ### Error 2: When Accessing /apps Endpoint ``` 2026-01-30 10:03:20,203 ERROR [app.py:875] 0ca8d8078e Exception on /console/api/apps [GET] Traceback (most recent call last): File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 917, in full_dispatch_request rv = self.dispatch_request() ^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 902, in dispatch_request return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/api.py", line 404, in wrapper resp = resource(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/views.py", line 110, in view return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/resource.py", line 41, in dispatch_request resp = meth(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 220, in decorated return view(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/libs/login.py", line 80, in decorated_view return current_app.ensure_sync(func)(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 37, in decorated return view(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 232, in decorated return view(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "/home/rhys/nht1206/dify/api/controllers/console/app/app.py", line 246, in get for _, node_data in workflow.walk_nodes(): File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in walk_nodes yield from ((node["id"], node["data"]) for node in graph_dict["nodes"]) File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in <genexpr> yield from ((node["id"], node["data"]) for node in graph_dict["nodes"]) ~~~~^^^^^^ KeyError: 'id' ```
yindo added the 🐞 bug label 2026-02-21 20:15:15 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Feb 1, 2026):

The crash happens because malformed workflow DSL imports (nodes missing required fields like 'id' and 'data') are not properly validated before saving, causing unhandled KeyErrors in workflow.py:walk_nodes() and leaving broken app records in the database. The app is committed to the database before workflow validation, so if the workflow fails, the app still exists and breaks the /apps page when listed.

To fix this, add strict validation for node structure (check for 'id' and 'data' in every node) before any database commit—ideally in WorkflowService.validate_graph_structure or a new helper. The entire import and app creation process should run inside a transaction so any failure rolls back all changes, keeping the database consistent. Defensive coding in walk_nodes() (e.g., raising a clear error if node keys are missing) will also prevent silent crashes. See the relevant code and validation gaps here and here.

For recovery, you may need to manually remove broken app records from the database to restore /apps page access until a fix is implemented.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Feb 1, 2026): <!-- Answer --> The crash happens because malformed workflow DSL imports (nodes missing required fields like 'id' and 'data') are not properly validated before saving, causing unhandled KeyErrors in `workflow.py:walk_nodes()` and leaving broken app records in the database. The app is committed to the database before workflow validation, so if the workflow fails, the app still exists and breaks the `/apps` page when listed. To fix this, add strict validation for node structure (check for 'id' and 'data' in every node) before any database commit—ideally in `WorkflowService.validate_graph_structure` or a new helper. The entire import and app creation process should run inside a transaction so any failure rolls back all changes, keeping the database consistent. Defensive coding in `walk_nodes()` (e.g., raising a clear error if node keys are missing) will also prevent silent crashes. See the relevant code and validation gaps [here](https://github.com/langgenius/dify/blob/3216b67bfa93417814dbdf05fd8d0e174df3c627/api/services/app_dsl_service.py#L120-L535) and [here](https://github.com/langgenius/dify/blob/3216b67bfa93417814dbdf05fd8d0e174df3c627/api/services/workflow_service.py#L193-L947). For recovery, you may need to manually remove broken app records from the database to restore `/apps` page access until a fix is implemented. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/f8a46025-513e-46a2-a2be-4a0decf8af00?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20crash%20happens%20because%20malformed%20workflow%20DSL%20imports%20%28nodes%20missing%20required%20fields%20like%20%27id%27%20and%20%27data%27%29%20are%20not%20properly%20validated%20before%20saving%2C%20causing%20unhandled%20KeyErrors%20in%20%60workflow.py%3Awalk_nodes%28%29%60%20and%20leaving%20broken%20app%20records%20in%20the%20database.%20The%20app%20is%20committed%20to%20the%20database%20before%20workflow%20validation%2C%20so%20if%20the%20workflow%20fails%2C%20the%20app%20still%20exists%20and%20breaks%20the%20%60/apps%60%20page%20when%20listed.%20%0A%0ATo%20fix%20this%2C%20add%20strict%20validation%20for%20node%20structure%20%28check%20for%20%27id%27%20and%20%27data%27%20in%20every%20node%29%20before%20any%20database%20commit%E2%80%94ideally%20in%20%60WorkflowService.validate_graph_structure%60%20or%20a%20new%20helper.%20The%20entire%20import%20and%20app%20creation%20process%20should%20run%20inside%20a%20transaction%20so%20any%20failure%20rolls%20back%20all%20changes%2C%20keeping%20the%20database%20consistent.%20Defensive%20coding%20in%20%60walk_nodes%28%29%60%20%28e.g.%2C%20raising%20a%20clear%20error%20if%20node%20keys%20are%20missing%29%20will%20also%20prevent%20silent%20crashes.%20See%20the%20relevant%20code%20and%20validation%20gaps%20%5Bhere%5D%28https%3A//github.com/langgenius/dify/blob/3216b67bfa93417814dbdf05fd8d0e174df3c627/api/services/app_dsl_service.py%23L120-L535%29%20and%20%5Bhere%5D%28https%3A//github.com/langgenius/dify/blob/3216b67bfa93417814dbdf05fd8d0e174df3c627/api/services/workflow_service.py%23L193-L947%29.%0A%0AFor%20recovery%2C%20you%20may%20need%20to%20manually%20remove%20broken%20app%20records%20from%20the%20database%20to%20restore%20%60/apps%60%20page%20access%20until%20a%20fix%20is%20implemented.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/31804)
Author
Owner

@fatelei commented on GitHub (Feb 1, 2026):

Self Checks

  • I have read the Contributing Guide and Language Policy.[x] This is only for bug report, if you would like to ask a question, please head to Discussions.[x] I have searched for existing issues search for existing issues, including closed ones.[x] I confirm that I am using English to submit this report, otherwise it will be closed.[x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)[x] Please do not modify this template :) and fill in all the required fields.

Dify version

1.12.0

Cloud or Self Hosted

Self Hosted (Source)

Steps to reproduce

  1. Attemp to import an app using the following DSL YAML content:

app:
description: ''
icon: 🤖
icon_background: '#FFEAD5'
mode: workflow
name: Test
use_icon_as_answer_icon: false
dependencies: []
kind: app
version: 0.5.0
workflow:
conversation_variables: []
environment_variables: []
features:
file_upload:
enabled: false
number_limits: 3
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
graph:
edges: []
nodes:
- data:
title: User Input
type: start
variables: []
id: '1769765767428'
position:
x: 80
y: 282
positionAbsolute:
x: 80
y: 282
sourcePosition: right
targetPosition: left
type: custom
- type: custom # This node is missing 'id' and 'data' fields
viewport:
x: 0
y: 0
zoom: 1
rag_pipeline_variables: []
3. The import will fail with an error
4. Navigate to the /apps page

✔️ Expected Behavior

  1. If it fails to import, no app should be created in the database
  2. The /apps page should remain functional even if some apps have issues

Actual Behavior

  1. The app is still imserted into the database despite the failure
  2. The /apps page crashes when trying to list apps, making it completely inaccessible
  3. The error occurs in workflow.py:360 in the walk_nodes() method

Error Logs

Error 1: During Import (but app still created)

2026-01-30 10:04:01,336 ERROR [app_dsl_service.py:326] 3b4f83761d Failed to import app
Traceback (most recent call last):
  File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 288, in import_app
    app = self._create_or_update_app(
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 525, in _create_or_update_app
    workflow_service.sync_draft_workflow(
  File "/home/rhys/nht1206/dify/api/services/workflow_service.py", line 246, in sync_draft_workflow
    app_draft_workflow_was_synced.send(app_model, synced_draft_workflow=workflow)
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/blinker/base.py", line 249, in send
    result = receiver(sender, **kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/events/event_handlers/sync_webhook_when_app_created.py", line 22, in handle
    WebhookService.sync_webhook_relationships(app, synced_draft_workflow)
  File "/home/rhys/nht1206/dify/api/services/trigger/webhook_service.py", line 832, in sync_webhook_relationships
    nodes_id_in_graph = [node_id for node_id, _ in workflow.walk_nodes(NodeType.TRIGGER_WEBHOOK)]
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 354, in walk_nodes
    yield from (
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 357, in <genexpr>
    if node["data"]["type"] == specific_node_type.value
       ~~~~^^^^^^^^
KeyError: 'data'

Error 2: When Accessing /apps Endpoint

2026-01-30 10:03:20,203 ERROR [app.py:875] 0ca8d8078e Exception on /console/api/apps [GET]
Traceback (most recent call last):
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 902, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/api.py", line 404, in wrapper
    resp = resource(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/views.py", line 110, in view
    return current_app.ensure_sync(self.dispatch_request)(**kwargs)  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/resource.py", line 41, in dispatch_request
    resp = meth(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 220, in decorated
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/libs/login.py", line 80, in decorated_view
    return current_app.ensure_sync(func)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 37, in decorated
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 232, in decorated
    return view(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/rhys/nht1206/dify/api/controllers/console/app/app.py", line 246, in get
    for _, node_data in workflow.walk_nodes():
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in walk_nodes
    yield from ((node["id"], node["data"]) for node in graph_dict["nodes"])
  File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in <genexpr>
    yield from ((node["id"], node["data"]) for node in graph_dict["nodes"])
                 ~~~~^^^^^^
KeyError: 'id'

the dsl is export in old version dify ?

@fatelei commented on GitHub (Feb 1, 2026): > ### Self Checks > * [x] I have read the [Contributing Guide](https://github.com/langgenius/dify/blob/main/CONTRIBUTING.md) and [Language Policy](https://github.com/langgenius/dify/issues/1542).[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, otherwise it will be closed.[x] 【中文用户 & Non English User】请使用英语提交,否则会被关闭 :)[x] Please do not modify this template :) and fill in all the required fields. > > ### Dify version > 1.12.0 > > ### Cloud or Self Hosted > Self Hosted (Source) > > ### Steps to reproduce > 1. Attemp to import an app using the following DSL YAML content: > > app: > description: '' > icon: 🤖 > icon_background: '#FFEAD5' > mode: workflow > name: Test > use_icon_as_answer_icon: false > dependencies: [] > kind: app > version: 0.5.0 > workflow: > conversation_variables: [] > environment_variables: [] > features: > file_upload: > enabled: false > number_limits: 3 > 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 > graph: > edges: [] > nodes: > - data: > title: User Input > type: start > variables: [] > id: '1769765767428' > position: > x: 80 > y: 282 > positionAbsolute: > x: 80 > y: 282 > sourcePosition: right > targetPosition: left > type: custom > - type: custom # This node is missing 'id' and 'data' fields > viewport: > x: 0 > y: 0 > zoom: 1 > rag_pipeline_variables: [] > 3. The import will fail with an error > 4. Navigate to the `/apps` page > > ### ✔️ Expected Behavior > 1. If it fails to import, no app should be created in the database > 2. The `/apps` page should remain functional even if some apps have issues > > ### ❌ Actual Behavior > 1. The app is still imserted into the database despite the failure > 2. The `/apps` page crashes when trying to list apps, making it completely inaccessible > 3. The error occurs in `workflow.py:360` in the `walk_nodes()` method > > ## Error Logs > ### Error 1: During Import (but app still created) > ``` > 2026-01-30 10:04:01,336 ERROR [app_dsl_service.py:326] 3b4f83761d Failed to import app > Traceback (most recent call last): > File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 288, in import_app > app = self._create_or_update_app( > ^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/services/app_dsl_service.py", line 525, in _create_or_update_app > workflow_service.sync_draft_workflow( > File "/home/rhys/nht1206/dify/api/services/workflow_service.py", line 246, in sync_draft_workflow > app_draft_workflow_was_synced.send(app_model, synced_draft_workflow=workflow) > File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/blinker/base.py", line 249, in send > result = receiver(sender, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/events/event_handlers/sync_webhook_when_app_created.py", line 22, in handle > WebhookService.sync_webhook_relationships(app, synced_draft_workflow) > File "/home/rhys/nht1206/dify/api/services/trigger/webhook_service.py", line 832, in sync_webhook_relationships > nodes_id_in_graph = [node_id for node_id, _ in workflow.walk_nodes(NodeType.TRIGGER_WEBHOOK)] > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/models/workflow.py", line 354, in walk_nodes > yield from ( > File "/home/rhys/nht1206/dify/api/models/workflow.py", line 357, in <genexpr> > if node["data"]["type"] == specific_node_type.value > ~~~~^^^^^^^^ > KeyError: 'data' > ``` > > ### Error 2: When Accessing /apps Endpoint > ``` > 2026-01-30 10:03:20,203 ERROR [app.py:875] 0ca8d8078e Exception on /console/api/apps [GET] > Traceback (most recent call last): > File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 917, in full_dispatch_request > rv = self.dispatch_request() > ^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/app.py", line 902, in dispatch_request > return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args) # type: ignore[no-any-return] > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/api.py", line 404, in wrapper > resp = resource(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask/views.py", line 110, in view > return current_app.ensure_sync(self.dispatch_request)(**kwargs) # type: ignore[no-any-return] > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/.venv/lib/python3.12/site-packages/flask_restx/resource.py", line 41, in dispatch_request > resp = meth(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 220, in decorated > return view(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/libs/login.py", line 80, in decorated_view > return current_app.ensure_sync(func)(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 37, in decorated > return view(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/controllers/console/wraps.py", line 232, in decorated > return view(*args, **kwargs) > ^^^^^^^^^^^^^^^^^^^^^ > File "/home/rhys/nht1206/dify/api/controllers/console/app/app.py", line 246, in get > for _, node_data in workflow.walk_nodes(): > File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in walk_nodes > yield from ((node["id"], node["data"]) for node in graph_dict["nodes"]) > File "/home/rhys/nht1206/dify/api/models/workflow.py", line 360, in <genexpr> > yield from ((node["id"], node["data"]) for node in graph_dict["nodes"]) > ~~~~^^^^^^ > KeyError: 'id' > ``` the dsl is export in old version dify ?
Author
Owner

@nht1206 commented on GitHub (Feb 1, 2026):

@fatelei It's not exported from older version.
The users might just edit the DSL, then import to the Dify.
And I just have to delete the app from database manually. Because the apps page crashes.

@nht1206 commented on GitHub (Feb 1, 2026): @fatelei It's not exported from older version. The users might just edit the DSL, then import to the Dify. And I just have to delete the app from database manually. Because the apps page crashes.
Author
Owner

@nht1206 commented on GitHub (Feb 1, 2026):

But it's better to prevent app creation when it failed to import a DSL, right?

@nht1206 commented on GitHub (Feb 1, 2026): But it's better to prevent app creation when it failed to import a DSL, right?
Author
Owner

@fatelei commented on GitHub (Feb 2, 2026):

But it's better to prevent app creation when it failed to import a DSL, right?

app create in dsl import, but it was not rollback when dsl import failed

@fatelei commented on GitHub (Feb 2, 2026): > But it's better to prevent app creation when it failed to import a DSL, right? app create in dsl import, but it was not rollback when dsl import failed
Author
Owner

@fatelei commented on GitHub (Feb 2, 2026):

But it's better to prevent app creation when it failed to import a DSL, right?

i submit a pr, allow transaction rollback when import dsl failed

@fatelei commented on GitHub (Feb 2, 2026): > But it's better to prevent app creation when it failed to import a DSL, right? i submit a pr, allow transaction rollback when import dsl failed
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#22011