[PR #17907] fix: fix IntegrityError in _handle_workflow_node_execution_success #28799

Closed
opened 2026-02-21 20:44:08 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langgenius/dify/pull/17907

State: closed
Merged: No


Summary

Resolves #15059.
This patch will fix a bug causing chat flow to be stuck in running state forever.

2025-04-08 21:11:50,654.654 ERROR [Dummy-147] [completion.py:138] - internal server error.
Traceback (most recent call last):
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 941, in do_execute
    cursor.execute(statement, parameters)
psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "workflow_node_execution_pkey"
DETAIL:  Key (id)=(6021088b-72cd-46b4-a227-bed9733f5250) already exists.


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/app/api/controllers/service_api/app/completion.py", line 115, in post
    response = AppGenerateService.generate(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/services/app_generate_service.py", line 81, in generate
    generator=AdvancedChatAppGenerator().generate(
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/app_generator.py", line 160, in generate
    return self._generate(
           ^^^^^^^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/app_generator.py", line 280, in _generate
    response = self._handle_advanced_chat_response(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/app_generator.py", line 384, in _handle_advanced_chat_response
    return generate_task_pipeline.process()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 154, in process
    return self._to_blocking_response(generator)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 161, in _to_blocking_response
    for stream_response in generator:
                           ^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 224, in _wrapper_process_stream_response
    for response in self._process_stream_response(tts_publisher=tts_publisher, trace_manager=trace_manager):
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 368, in _process_stream_response
    session.commit()
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2028, in commit
    trans.commit(_to_root=True)
  File "<string>", line 2, in commit
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
    ret_value = fn(self, *arg, **kw)
                ^^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1313, in commit
    self._prepare_impl()
  File "<string>", line 2, in _prepare_impl
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
    ret_value = fn(self, *arg, **kw)
                ^^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl
    self.session.flush()
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 4352, in flush
    self._flush(objects)
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 4487, in _flush
    with util.safe_reraise():
         ^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 4448, in _flush
    flush_context.execute()
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute
    rec.execute(self)
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute
    util.preloaded.orm_persistence.save_obj(
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj
    _emit_insert_statements(
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/persistence.py", line 1048, in _emit_insert_statements
    result = connection.execute(
             ^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1418, in execute
    return meth(
           ^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/sql/elements.py", line 515, in _execute_on_connection
    return connection._execute_clauseelement(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1640, in _execute_clauseelement
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context
    return self._exec_single_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context
    self._handle_dbapi_exception(
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context
    self.dialect.do_execute(
  File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 941, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "workflow_node_execution_pkey"
DETAIL:  Key (id)=(6021088b-72cd-46b4-a227-bed9733f5250) already exists.

Checking the Cache Before Querying the Database

If the object exists in the cache:
Retrieve its id (assumed to be a UUID) and use session.get() to fetch it from the database.

If the object is not found in the database:
This indicates that the record doesn't exist yet. In this case, use session.add(cached) to add it to the current session, and then call session.flush() to write it to the database.
This ensures that subsequent modifications to the object will perform an UPDATE operation instead of attempting an INSERT.

If the object is found: Return the attached object from the current session for further update operations.

Ensuring Smooth Workflow Execution

The modified code ensures that when the corresponding record doesn't exist in the database, a new record is automatically inserted and then updated. This approach maintains the continuity of the workflow and avoids issues where merge might mistakenly attempt an INSERT, leading to primary key conflicts.

Screenshots

Before After
... ...
截屏2025-04-11 23 06 41

Checklist

Important

Please review the checklist below before submitting your pull request.

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran dev/reformat(backend) and cd web && npx lint-staged(frontend) to appease the lint gods
**Original Pull Request:** https://github.com/langgenius/dify/pull/17907 **State:** closed **Merged:** No --- # Summary Resolves #15059. This patch will fix a bug causing chat flow to be stuck in running state forever. ``` 2025-04-08 21:11:50,654.654 ERROR [Dummy-147] [completion.py:138] - internal server error. Traceback (most recent call last): File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context self.dialect.do_execute( File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 941, in do_execute cursor.execute(statement, parameters) psycopg2.errors.UniqueViolation: duplicate key value violates unique constraint "workflow_node_execution_pkey" DETAIL: Key (id)=(6021088b-72cd-46b4-a227-bed9733f5250) already exists. The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/app/api/controllers/service_api/app/completion.py", line 115, in post response = AppGenerateService.generate( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/services/app_generate_service.py", line 81, in generate generator=AdvancedChatAppGenerator().generate( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/app_generator.py", line 160, in generate return self._generate( ^^^^^^^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/app_generator.py", line 280, in _generate response = self._handle_advanced_chat_response( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/app_generator.py", line 384, in _handle_advanced_chat_response return generate_task_pipeline.process() ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 154, in process return self._to_blocking_response(generator) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 161, in _to_blocking_response for stream_response in generator: ^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 224, in _wrapper_process_stream_response for response in self._process_stream_response(tts_publisher=tts_publisher, trace_manager=trace_manager): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/core/app/apps/advanced_chat/generate_task_pipeline.py", line 368, in _process_stream_response session.commit() File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 2028, in commit trans.commit(_to_root=True) File "<string>", line 2, in commit File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go ret_value = fn(self, *arg, **kw) ^^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1313, in commit self._prepare_impl() File "<string>", line 2, in _prepare_impl File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go ret_value = fn(self, *arg, **kw) ^^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 1288, in _prepare_impl self.session.flush() File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 4352, in flush self._flush(objects) File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 4487, in _flush with util.safe_reraise(): ^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__ raise exc_value.with_traceback(exc_tb) File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/session.py", line 4448, in _flush flush_context.execute() File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/unitofwork.py", line 466, in execute rec.execute(self) File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/unitofwork.py", line 642, in execute util.preloaded.orm_persistence.save_obj( File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj _emit_insert_statements( File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/orm/persistence.py", line 1048, in _emit_insert_statements result = connection.execute( ^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1418, in execute return meth( ^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/sql/elements.py", line 515, in _execute_on_connection return connection._execute_clauseelement( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1640, in _execute_clauseelement ret = self._execute_context( ^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1846, in _execute_context return self._exec_single_context( ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1986, in _exec_single_context self._handle_dbapi_exception( File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 2355, in _handle_dbapi_exception raise sqlalchemy_exception.with_traceback(exc_info[2]) from e File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/base.py", line 1967, in _exec_single_context self.dialect.do_execute( File "/app/api/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 941, in do_execute cursor.execute(statement, parameters) sqlalchemy.exc.IntegrityError: (psycopg2.errors.UniqueViolation) duplicate key value violates unique constraint "workflow_node_execution_pkey" DETAIL: Key (id)=(6021088b-72cd-46b4-a227-bed9733f5250) already exists. ``` # Checking the Cache Before Querying the Database If the object exists in the cache: Retrieve its id (assumed to be a UUID) and use session.get() to fetch it from the database. If the object is not found in the database: This indicates that the record doesn't exist yet. In this case, use session.add(cached) to add it to the current session, and then call session.flush() to write it to the database. This ensures that subsequent modifications to the object will perform an UPDATE operation instead of attempting an INSERT. If the object is found: Return the attached object from the current session for further update operations. # Ensuring Smooth Workflow Execution The modified code ensures that when the corresponding record doesn't exist in the database, a new record is automatically inserted and then updated. This approach maintains the continuity of the workflow and avoids issues where merge might mistakenly attempt an INSERT, leading to primary key conflicts. # Screenshots | Before | After | |--------|-------| | ... | ... | <img width="1033" alt="截屏2025-04-11 23 06 41" src="https://github.com/user-attachments/assets/a89c19fd-836d-43cd-ba40-0f2c8b8663a9" /> # Checklist > [!IMPORTANT] > Please review the checklist below before submitting your pull request. - [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs) - [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!) - [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change. - [x] I've updated the documentation accordingly. - [x] I ran `dev/reformat`(backend) and `cd web && npx lint-staged`(frontend) to appease the lint gods
yindo added the pull-request label 2026-02-21 20:44:08 -05:00
yindo closed this issue 2026-02-21 20:44:09 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#28799