500 Error for /apps/{app_id}/workflows/draft/conversation-variables API #21459

Closed
opened 2026-02-21 20:12:38 -05:00 by yindo · 4 comments
Owner

Originally created by @lyzno1 on GitHub (Jan 6, 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

latest

Cloud or Self Hosted

Cloud, Self Hosted (Source)

Steps to reproduce

Analysis Report on 500 Error for /apps/{app_id}/workflows/draft/conversation-variables API

Problem Description

When uploading a workflow via DSL, the backend API
/apps/{app_id}/workflows/draft/conversation-variables returns a 500 Internal Server Error.

Root Cause Analysis

This issue is caused by a backend code bug. The detailed analysis is as follows:

  1. Code Location
    The problem is located in the _model_to_insertion_dict function within
    api/services/workflow_draft_variable_service.py.

  2. Core Issue
    This function is responsible for converting WorkflowDraftVariable objects into dictionaries for bulk database insertion. However, it omits the id field in the generated insertion data.

  3. Database Constraint
    The id column of the workflow_draft_variables table is defined as the primary key with a NOT NULL constraint and does not have a database-level default value.

  4. Failure Trigger
    When the API attempts to bulk insert workflow draft variables, the generated insertion records contain NULL for the id field. This violates the database’s non-null constraint and causes the database to throw an exception, which ultimately results in a 500 Internal Server Error.

Conclusion

This is a backend logic error. The issue can be resolved by ensuring that the id field is properly included when constructing the insertion dictionary in the Python code.

✔️ Expected Behavior

n/a

Actual Behavior

No response

Originally created by @lyzno1 on GitHub (Jan 6, 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 latest ### Cloud or Self Hosted Cloud, Self Hosted (Source) ### Steps to reproduce # Analysis Report on 500 Error for `/apps/{app_id}/workflows/draft/conversation-variables` API ## Problem Description When uploading a workflow via DSL, the backend API `/apps/{app_id}/workflows/draft/conversation-variables` returns a `500 Internal Server Error`. ## Root Cause Analysis This issue is caused by a backend code bug. The detailed analysis is as follows: 1. **Code Location** The problem is located in the `_model_to_insertion_dict` function within `api/services/workflow_draft_variable_service.py`. 2. **Core Issue** This function is responsible for converting `WorkflowDraftVariable` objects into dictionaries for bulk database insertion. However, it **omits the `id` field** in the generated insertion data. 3. **Database Constraint** The `id` column of the `workflow_draft_variables` table is defined as the primary key with a `NOT NULL` constraint and does not have a database-level default value. 4. **Failure Trigger** When the API attempts to bulk insert workflow draft variables, the generated insertion records contain `NULL` for the `id` field. This violates the database’s non-null constraint and causes the database to throw an exception, which ultimately results in a `500 Internal Server Error`. ## Conclusion This is a backend logic error. The issue can be resolved by ensuring that the `id` field is properly included when constructing the insertion dictionary in the Python code. ### ✔️ Expected Behavior n/a ### ❌ Actual Behavior _No response_
yindo added the 🐞 bug label 2026-02-21 20:12:38 -05:00
yindo closed this issue 2026-02-21 20:12:38 -05:00
Author
Owner

@lyzno1 commented on GitHub (Jan 6, 2026):

@dosu give some context.

@lyzno1 commented on GitHub (Jan 6, 2026): @dosu give some context.
Author
Owner

@dosubot[bot] commented on GitHub (Jan 6, 2026):

Here's the context: The 500 error on the /apps/{app_id}/workflows/draft/conversation-variables API happens when uploading a workflow via DSL. The root cause is a backend bug in the _model_to_insertion_dict function (in api/services/workflow_draft_variable_service.py), which omits the id field when preparing data for bulk insertion. Since the workflow_draft_variables table requires id as a non-null primary key with no default, this omission causes the database to reject the insert and triggers the 500 error. No other issues or merged PRs currently address this specific bug, so this report is unique and highlights a real backend logic error.

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 (Jan 6, 2026): <!-- Answer --> Here's the context: The 500 error on the /apps/{app_id}/workflows/draft/conversation-variables API happens when uploading a workflow via DSL. The root cause is a backend bug in the _model_to_insertion_dict function (in api/services/workflow_draft_variable_service.py), which omits the id field when preparing data for bulk insertion. Since the workflow_draft_variables table requires id as a non-null primary key with no default, this omission causes the database to reject the insert and triggers the 500 error. No other issues or merged PRs currently address this specific bug, so this report is unique and highlights a real backend logic error. <!-- 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/0309cb1b-c16e-4486-8cf8-55715d2d93c8?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/0309cb1b-c16e-4486-8cf8-55715d2d93c8?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/0309cb1b-c16e-4486-8cf8-55715d2d93c8?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/0309cb1b-c16e-4486-8cf8-55715d2d93c8?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/0309cb1b-c16e-4486-8cf8-55715d2d93c8?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/0309cb1b-c16e-4486-8cf8-55715d2d93c8?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/0309cb1b-c16e-4486-8cf8-55715d2d93c8?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=Here%27s%20the%20context%3A%20The%20500%20error%20on%20the%20/apps/%7Bapp_id%7D/workflows/draft/conversation-variables%20API%20happens%20when%20uploading%20a%20workflow%20via%20DSL.%20The%20root%20cause%20is%20a%20backend%20bug%20in%20the%20_model_to_insertion_dict%20function%20%28in%20api/services/workflow_draft_variable_service.py%29%2C%20which%20omits%20the%20id%20field%20when%20preparing%20data%20for%20bulk%20insertion.%20Since%20the%20workflow_draft_variables%20table%20requires%20id%20as%20a%20non-null%20primary%20key%20with%20no%20default%2C%20this%20omission%20causes%20the%20database%20to%20reject%20the%20insert%20and%20triggers%20the%20500%20error.%20No%20other%20issues%20or%20merged%20PRs%20currently%20address%20this%20specific%20bug%2C%20so%20this%20report%20is%20unique%20and%20highlights%20a%20real%20backend%20logic%20error.)&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/30602)
Author
Owner

@lyzno1 commented on GitHub (Jan 6, 2026):

@dosu explore codebase and give some suggestions.

@lyzno1 commented on GitHub (Jan 6, 2026): @dosu explore codebase and give some suggestions.
Author
Owner

@dosubot[bot] commented on GitHub (Jan 6, 2026):

The root cause is that _model_to_insertion_dict omits the id field when preparing dictionaries for bulk insert, which violates the NOT NULL PK constraint on workflow_draft_variables and triggers the 500 error. The id field is only auto-generated when using the ORM, but the current batch insert logic bypasses the ORM, so id must be set manually in the dict.

To fix this, update _model_to_insertion_dict to always include the id field. For example:

def _model_to_insertion_dict(model: WorkflowDraftVariable) -> dict[str, Any]:
    d = {
        "id": model.id or str(uuid4()),
        "app_id": model.app_id,
        "last_edited_at": None,
        "node_id": model.node_id,
        "name": model.name,
        "selector": model.selector,
        "value_type": model.value_type,
        "value": model.value,
        "node_execution_id": model.node_execution_id,
        "file_id": model.file_id,
    }
    if model.visible is not None:
        d["visible"] = model.visible
    if model.editable is not None:
        d["editable"] = model.editable
    if model.created_at is not None:
        d["created_at"] = model.created_at
    if model.updated_at is not None:
        d["updated_at"] = model.updated_at
    if model.description is not None:
        d["description"] = model.description
    return d

This ensures every inserted row has a valid id, preventing the constraint violation and 500 error (source, source). After making this change, regression test by uploading workflows via DSL and confirming the API no longer returns a 500.

Best practice: always include all NOT NULL fields, especially PKs, in bulk insert dicts. Consider centralizing this logic if you have other manual bulk insert helpers. No other similar bugs were found elsewhere in the codebase, but a quick audit of any other manual dict builders is recommended.

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 (Jan 6, 2026): <!-- Answer --> The root cause is that `_model_to_insertion_dict` omits the id field when preparing dictionaries for bulk insert, which violates the NOT NULL PK constraint on workflow_draft_variables and triggers the 500 error. The id field is only auto-generated when using the ORM, but the current batch insert logic bypasses the ORM, so id must be set manually in the dict. To fix this, update `_model_to_insertion_dict` to always include the id field. For example: ```python def _model_to_insertion_dict(model: WorkflowDraftVariable) -> dict[str, Any]: d = { "id": model.id or str(uuid4()), "app_id": model.app_id, "last_edited_at": None, "node_id": model.node_id, "name": model.name, "selector": model.selector, "value_type": model.value_type, "value": model.value, "node_execution_id": model.node_execution_id, "file_id": model.file_id, } if model.visible is not None: d["visible"] = model.visible if model.editable is not None: d["editable"] = model.editable if model.created_at is not None: d["created_at"] = model.created_at if model.updated_at is not None: d["updated_at"] = model.updated_at if model.description is not None: d["description"] = model.description return d ``` This ensures every inserted row has a valid id, preventing the constraint violation and 500 error ([source](https://github.com/langgenius/dify/blob/89463cc11d7fa2fce0a94c968d6d316bf4423695/api/services/workflow_draft_variable_service.py#L185-L702), [source](https://github.com/langgenius/dify/blob/89463cc11d7fa2fce0a94c968d6d316bf4423695/api/models/workflow.py#L1203-L1584)). After making this change, regression test by uploading workflows via DSL and confirming the API no longer returns a 500. Best practice: always include all NOT NULL fields, especially PKs, in bulk insert dicts. Consider centralizing this logic if you have other manual bulk insert helpers. No other similar bugs were found elsewhere in the codebase, but a quick audit of any other manual dict builders is recommended. <!-- 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/690b1d9d-4a03-44ca-adb1-a0e5ada45516?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/690b1d9d-4a03-44ca-adb1-a0e5ada45516?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/690b1d9d-4a03-44ca-adb1-a0e5ada45516?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/690b1d9d-4a03-44ca-adb1-a0e5ada45516?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/690b1d9d-4a03-44ca-adb1-a0e5ada45516?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/690b1d9d-4a03-44ca-adb1-a0e5ada45516?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/690b1d9d-4a03-44ca-adb1-a0e5ada45516?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%20root%20cause%20is%20that%20%60_model_to_insertion_dict%60%20omits%20the%20id%20field%20when%20preparing%20dictionaries%20for%20bulk%20insert%2C%20which%20violates%20the%20NOT%20NULL%20PK%20constraint%20on%20workflow_draft_variables%20and%20triggers%20the%20500%20error.%20The%20id%20field%20is%20only%20auto-generated%20when%20using%20the%20ORM%2C%20but%20the%20current%20batch%20insert%20logic%20bypasses%20the%20ORM%2C%20so%20id%20must%20be%20set%20manually%20in%20the%20dict.%0A%0ATo%20fix%20this%2C%20update%20%60_model_to_insertion_dict%60%20to%20always%20include%20the%20id%20field.%20For%20example%3A%0A%0A%60%60%60python%0Adef%20_model_to_insertion_dict%28model%3A%20WorkflowDraftVariable%29%20-%3E%20dict%5Bstr%2C%20Any%5D%3A%0A%20%20%20%20d%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22id%22%3A%20model.id%20or%20str%28uuid4%28%29%29%2C%0A%20%20%20%20%20%20%20%20%22app_id%22%3A%20model.app_id%2C%0A%20%20%20%20%20%20%20%20%22last_edited_at%22%3A%20None%2C%0A%20%20%20%20%20%20%20%20%22node_id%22%3A%20model.node_id%2C%0A%20%20%20%20%20%20%20%20%22name%22%3A%20model.name%2C%0A%20%20%20%20%20%20%20%20%22selector%22%3A%20model.selector%2C%0A%20%20%20%20%20%20%20%20%22value_type%22%3A%20model.value_type%2C%0A%20%20%20%20%20%20%20%20%22value%22%3A%20model.value%2C%0A%20%20%20%20%20%20%20%20%22node_execution_id%22%3A%20model.node_execution_id%2C%0A%20%20%20%20%20%20%20%20%22file_id%22%3A%20model.file_id%2C%0A%20%20%20%20%7D%0A%20%20%20%20if%20model.visible%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20d%5B%22visible%22%5D%20%3D%20model.visible%0A%20%20%20%20if%20model.editable%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20d%5B%22editable%22%5D%20%3D%20model.editable%0A%20%20%20%20if%20model.created_at%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20d%5B%22created_at%22%5D%20%3D%20model.created_at%0A%20%20%20%20if%20model.updated_at%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20d%5B%22updated_at%22%5D%20%3D%20model.updated_at%0A%20%20%20%20if%20model.description%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20d%5B%22description%22%5D%20%3D%20model.description%0A%20%20%20%20return%20d%0A%60%60%60%0A%0AThis%20ensures%20every%20inserted%20row%20has%20a%20valid%20id%2C%20preventing%20the%20constraint%20violation%20and%20500%20error%20%28%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/89463cc11d7fa2fce0a94c968d6d316bf4423695/api/services/workflow_draft_variable_service.py%23L185-L702%29%2C%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/89463cc11d7fa2fce0a94c968d6d316bf4423695/api/models/workflow.py%23L1203-L1584%29%29.%20After%20making%20this%20change%2C%20regression%20test%20by%20uploading%20workflows%20via%20DSL%20and%20confirming%20the%20API%20no%20longer%20returns%20a%20500.%0A%0ABest%20practice%3A%20always%20include%20all%20NOT%20NULL%20fields%2C%20especially%20PKs%2C%20in%20bulk%20insert%20dicts.%20Consider%20centralizing%20this%20logic%20if%20you%20have%20other%20manual%20bulk%20insert%20helpers.%20No%20other%20similar%20bugs%20were%20found%20elsewhere%20in%20the%20codebase%2C%20but%20a%20quick%20audit%20of%20any%20other%20manual%20dict%20builders%20is%20recommended.)&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/30602)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#21459