Tool file xxxx does not exist,when DB_TYPE is mysql #20725

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

Originally created by @batscars on GitHub (Dec 1, 2025).

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.10.1

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

An image generation API was defined using a custom API tool. After an image is successfully generated, a record is first written into the ToolFile table in the database, and then immediately queried. In the MySQL scenario, this newly inserted record cannot be retrieved.

✔️ Expected Behavior

The image can be successfully retrieved and displayed.

Actual Behavior

ValueError: ToolFile 7bd4a8e1-a349-42bf-8ff7-6428d63b0611 not found

Image Image
Originally created by @batscars on GitHub (Dec 1, 2025). ### 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.10.1 ### Cloud or Self Hosted Self Hosted (Docker) ### Steps to reproduce An image generation API was defined using a custom API tool. After an image is successfully generated, a record is first written into the ToolFile table in the database, and then immediately queried. In the MySQL scenario, this newly inserted record cannot be retrieved. ### ✔️ Expected Behavior The image can be successfully retrieved and displayed. ### ❌ Actual Behavior ValueError: ToolFile 7bd4a8e1-a349-42bf-8ff7-6428d63b0611 not found <img width="702" height="165" alt="Image" src="https://github.com/user-attachments/assets/4fe500e0-0563-4e18-b351-ce566d1e2c55" /> <img width="1029" height="211" alt="Image" src="https://github.com/user-attachments/assets/c36c7c22-04e0-4641-8531-a5f794609ae2" />
yindo added the 🐞 bug label 2026-02-21 20:08:39 -05:00
yindo closed this issue 2026-02-21 20:08:39 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Dec 1, 2025):

This is a known issue with MySQL in Dify v1.10.1. There are two main root causes:

  1. UUID format mismatch: MySQL stores UUIDs as 36-character hyphenated strings, but some queries use 32-character hex strings without dashes, leading to empty results. Make sure the UUID you use for queries matches the format stored in the database (usually hyphenated). You can patch the StringUUID type or sanitize UUIDs before querying to ensure consistency. More details and workarounds are discussed here.

  2. MySQL transaction/session isolation: If you insert a ToolFile record in one session and immediately query it in another, MySQL’s default REPEATABLE READ isolation may cause the new session to see a stale snapshot and miss the new row. This doesn’t happen with PostgreSQL’s READ COMMITTED default. To work around this, try reading the record in the same session after commit, or refactor your workflow so that reads happen after the transaction is fully committed and the session is closed. See related session handling advice here.

Recent PRs have improved MySQL compatibility and UUID handling (PR #28730, PR #28506). Upgrading to a version that includes these changes is recommended if possible.

For best results with MySQL, use the correct URI scheme (mysql+pymysql) and avoid passing ORM objects between threads or workflow steps—always pass IDs and re-query inside a session context.

Let me know if you need code examples or more details on patching UUID handling or session management.

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 (Dec 1, 2025): <!-- Answer --> This is a known issue with MySQL in Dify v1.10.1. There are two main root causes: 1. **UUID format mismatch:** MySQL stores UUIDs as 36-character hyphenated strings, but some queries use 32-character hex strings without dashes, leading to empty results. Make sure the UUID you use for queries matches the format stored in the database (usually hyphenated). You can patch the `StringUUID` type or sanitize UUIDs before querying to ensure consistency. More details and workarounds are discussed [here](https://github.com/langgenius/dify/issues/28942). 2. **MySQL transaction/session isolation:** If you insert a ToolFile record in one session and immediately query it in another, MySQL’s default REPEATABLE READ isolation may cause the new session to see a stale snapshot and miss the new row. This doesn’t happen with PostgreSQL’s READ COMMITTED default. To work around this, try reading the record in the same session after commit, or refactor your workflow so that reads happen after the transaction is fully committed and the session is closed. See related session handling advice [here](https://github.com/langgenius/dify/issues/27192). Recent PRs have improved MySQL compatibility and UUID handling ([PR #28730](https://github.com/langgenius/dify/pull/28730), [PR #28506](https://github.com/langgenius/dify/pull/28506)). Upgrading to a version that includes these changes is recommended if possible. For best results with MySQL, use the correct URI scheme (`mysql+pymysql`) and avoid passing ORM objects between threads or workflow steps—always pass IDs and re-query inside a session context. Let me know if you need code examples or more details on patching UUID handling or session management. <!-- 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/afd9e591-6fd8-4788-8846-4fd34264d33f?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/afd9e591-6fd8-4788-8846-4fd34264d33f?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/afd9e591-6fd8-4788-8846-4fd34264d33f?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/afd9e591-6fd8-4788-8846-4fd34264d33f?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/afd9e591-6fd8-4788-8846-4fd34264d33f?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/afd9e591-6fd8-4788-8846-4fd34264d33f?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/afd9e591-6fd8-4788-8846-4fd34264d33f?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=This%20is%20a%20known%20issue%20with%20MySQL%20in%20Dify%20v1.10.1.%20There%20are%20two%20main%20root%20causes%3A%0A%0A1.%20%2A%2AUUID%20format%20mismatch%3A%2A%2A%20MySQL%20stores%20UUIDs%20as%2036-character%20hyphenated%20strings%2C%20but%20some%20queries%20use%2032-character%20hex%20strings%20without%20dashes%2C%20leading%20to%20empty%20results.%20Make%20sure%20the%20UUID%20you%20use%20for%20queries%20matches%20the%20format%20stored%20in%20the%20database%20%28usually%20hyphenated%29.%20You%20can%20patch%20the%20%60StringUUID%60%20type%20or%20sanitize%20UUIDs%20before%20querying%20to%20ensure%20consistency.%20More%20details%20and%20workarounds%20are%20discussed%20%5Bhere%5D%28https%3A//github.com/langgenius/dify/issues/28942%29.%0A%0A2.%20%2A%2AMySQL%20transaction/session%20isolation%3A%2A%2A%20If%20you%20insert%20a%20ToolFile%20record%20in%20one%20session%20and%20immediately%20query%20it%20in%20another%2C%20MySQL%E2%80%99s%20default%20REPEATABLE%20READ%20isolation%20may%20cause%20the%20new%20session%20to%20see%20a%20stale%20snapshot%20and%20miss%20the%20new%20row.%20This%20doesn%E2%80%99t%20happen%20with%20PostgreSQL%E2%80%99s%20READ%20COMMITTED%20default.%20To%20work%20around%20this%2C%20try%20reading%20the%20record%20in%20the%20same%20session%20after%20commit%2C%20or%20refactor%20your%20workflow%20so%20that%20reads%20happen%20after%20the%20transaction%20is%20fully%20committed%20and%20the%20session%20is%20closed.%20See%20related%20session%20handling%20advice%20%5Bhere%5D%28https%3A//github.com/langgenius/dify/issues/27192%29.%0A%0ARecent%20PRs%20have%20improved%20MySQL%20compatibility%20and%20UUID%20handling%20%28%5BPR%20%2328730%5D%28https%3A//github.com/langgenius/dify/pull/28730%29%2C%20%5BPR%20%2328506%5D%28https%3A//github.com/langgenius/dify/pull/28506%29%29.%20Upgrading%20to%20a%20version%20that%20includes%20these%20changes%20is%20recommended%20if%20possible.%0A%0AFor%20best%20results%20with%20MySQL%2C%20use%20the%20correct%20URI%20scheme%20%28%60mysql%2Bpymysql%60%29%20and%20avoid%20passing%20ORM%20objects%20between%20threads%20or%20workflow%20steps%E2%80%94always%20pass%20IDs%20and%20re-query%20inside%20a%20session%20context.%0A%0ALet%20me%20know%20if%20you%20need%20code%20examples%20or%20more%20details%20on%20patching%20UUID%20handling%20or%20session%20management.)&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/28999)
Author
Owner

@batscars commented on GitHub (Dec 1, 2025):

@dosu I have already upgrade to latest main branch, but the question still happens

@batscars commented on GitHub (Dec 1, 2025): @dosu I have already upgrade to latest main branch, but the question still happens
Author
Owner

@dosubot[bot] commented on GitHub (Dec 1, 2025):

This issue can still happen on the latest main branch because the code for ToolFile operations (like in DatasourceFileManager) still uses the global db.session for both insert and query, without explicit session scoping or refresh. In MySQL, this can cause visibility problems due to the default REPEATABLE READ isolation—especially if the session is reused or long-lived, or if insert and query happen in different sessions or transactions. This means a newly inserted ToolFile might not be visible to a subsequent query right away, even after commit, if the session/connection hasn't been refreshed or restarted. source

To help diagnose and resolve this, could you provide:

  • The exact commit hash or version you are running, and your MySQL version.
  • Confirmation that all database migrations have been applied.
  • Whether the insert and query for ToolFile are happening in the same session/transaction or across different ones.
  • The actual UUID values being inserted and queried, and whether they are hyphenated or hex-only.

As a workaround, try wrapping both the insert and the query in the same context-managed session (using with Session(db.engine) as session:) and see if the issue persists. If it works, you may need to refactor your code to always use context-managed sessions for these operations, rather than relying on the global db.session. This pattern is now recommended throughout Dify to avoid these MySQL-specific issues. source

If you can, enable SQLAlchemy debug logging to capture session/transaction behavior during the failing operation and share any relevant logs. This will help pinpoint if it's a session visibility or UUID format issue.

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 (Dec 1, 2025): <!-- Answer --> This issue can still happen on the latest main branch because the code for ToolFile operations (like in DatasourceFileManager) still uses the global db.session for both insert and query, without explicit session scoping or refresh. In MySQL, this can cause visibility problems due to the default REPEATABLE READ isolation—especially if the session is reused or long-lived, or if insert and query happen in different sessions or transactions. This means a newly inserted ToolFile might not be visible to a subsequent query right away, even after commit, if the session/connection hasn't been refreshed or restarted. [source](https://github.com/langgenius/dify/blob/e8f93380d1e260017f2483c5f410a5cfb0a0219c/api/core/datasource/datasource_file_manager.py#L105-L188) To help diagnose and resolve this, could you provide: - The exact commit hash or version you are running, and your MySQL version. - Confirmation that all database migrations have been applied. - Whether the insert and query for ToolFile are happening in the same session/transaction or across different ones. - The actual UUID values being inserted and queried, and whether they are hyphenated or hex-only. As a workaround, try wrapping both the insert and the query in the same context-managed session (using with Session(db.engine) as session:) and see if the issue persists. If it works, you may need to refactor your code to always use context-managed sessions for these operations, rather than relying on the global db.session. This pattern is now recommended throughout Dify to avoid these MySQL-specific issues. [source](https://github.com/langgenius/dify/issues/22929#issuecomment-3114380695) If you can, enable SQLAlchemy debug logging to capture session/transaction behavior during the failing operation and share any relevant logs. This will help pinpoint if it's a session visibility or UUID format issue. <!-- 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/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/b86e67f2-1fa4-4a59-9604-0fbb3ab1a529?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=This%20issue%20can%20still%20happen%20on%20the%20latest%20main%20branch%20because%20the%20code%20for%20ToolFile%20operations%20%28like%20in%20DatasourceFileManager%29%20still%20uses%20the%20global%20db.session%20for%20both%20insert%20and%20query%2C%20without%20explicit%20session%20scoping%20or%20refresh.%20In%20MySQL%2C%20this%20can%20cause%20visibility%20problems%20due%20to%20the%20default%20REPEATABLE%20READ%20isolation%E2%80%94especially%20if%20the%20session%20is%20reused%20or%20long-lived%2C%20or%20if%20insert%20and%20query%20happen%20in%20different%20sessions%20or%20transactions.%20This%20means%20a%20newly%20inserted%20ToolFile%20might%20not%20be%20visible%20to%20a%20subsequent%20query%20right%20away%2C%20even%20after%20commit%2C%20if%20the%20session/connection%20hasn%27t%20been%20refreshed%20or%20restarted.%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/e8f93380d1e260017f2483c5f410a5cfb0a0219c/api/core/datasource/datasource_file_manager.py%23L105-L188%29%0A%0ATo%20help%20diagnose%20and%20resolve%20this%2C%20could%20you%20provide%3A%0A-%20The%20exact%20commit%20hash%20or%20version%20you%20are%20running%2C%20and%20your%20MySQL%20version.%0A-%20Confirmation%20that%20all%20database%20migrations%20have%20been%20applied.%0A-%20Whether%20the%20insert%20and%20query%20for%20ToolFile%20are%20happening%20in%20the%20same%20session/transaction%20or%20across%20different%20ones.%0A-%20The%20actual%20UUID%20values%20being%20inserted%20and%20queried%2C%20and%20whether%20they%20are%20hyphenated%20or%20hex-only.%0A%0AAs%20a%20workaround%2C%20try%20wrapping%20both%20the%20insert%20and%20the%20query%20in%20the%20same%20context-managed%20session%20%28using%20with%20Session%28db.engine%29%20as%20session%3A%29%20and%20see%20if%20the%20issue%20persists.%20If%20it%20works%2C%20you%20may%20need%20to%20refactor%20your%20code%20to%20always%20use%20context-managed%20sessions%20for%20these%20operations%2C%20rather%20than%20relying%20on%20the%20global%20db.session.%20This%20pattern%20is%20now%20recommended%20throughout%20Dify%20to%20avoid%20these%20MySQL-specific%20issues.%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/issues/22929%23issuecomment-3114380695%29%0A%0AIf%20you%20can%2C%20enable%20SQLAlchemy%20debug%20logging%20to%20capture%20session/transaction%20behavior%20during%20the%20failing%20operation%20and%20share%20any%20relevant%20logs.%20This%20will%20help%20pinpoint%20if%20it%27s%20a%20session%20visibility%20or%20UUID%20format%20issue.)&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/28999)
Author
Owner

@batscars commented on GitHub (Dec 1, 2025):

@dosu
insert

        with Session(db.engine, expire_on_commit=False) as session:
            tool_file = ToolFile(
                user_id=user_id,
                tenant_id=tenant_id,
                conversation_id=conversation_id,
                file_key=filepath,
                mimetype=mimetype,
                original_url=file_url,
                name=filename,
                size=len(blob),
            )

            session.add(tool_file)
            session.commit()

query

                with Session(db.engine) as session:
                    stmt = select(ToolFile).where(ToolFile.id == tool_file_id)
                    tool_file = session.scalar(stmt)
                    if tool_file is None:
                        raise ToolFileError(f"Tool file {tool_file_id} does not exist")

when i add session.execute(sql_text("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")) before select, it works,but it is not elegant

@batscars commented on GitHub (Dec 1, 2025): @dosu insert ``` with Session(db.engine, expire_on_commit=False) as session: tool_file = ToolFile( user_id=user_id, tenant_id=tenant_id, conversation_id=conversation_id, file_key=filepath, mimetype=mimetype, original_url=file_url, name=filename, size=len(blob), ) session.add(tool_file) session.commit() ``` query ``` with Session(db.engine) as session: stmt = select(ToolFile).where(ToolFile.id == tool_file_id) tool_file = session.scalar(stmt) if tool_file is None: raise ToolFileError(f"Tool file {tool_file_id} does not exist") ``` when i add ```session.execute(sql_text("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"))``` before select, it works,but it is not elegant
Author
Owner

@dosubot[bot] commented on GitHub (Dec 1, 2025):

This happens because MySQL’s default isolation level is REPEATABLE READ, so a new session may not immediately see rows committed by another session. Manually setting the isolation level to READ COMMITTED per session works, but it’s not elegant and Dify doesn’t configure this globally by default.

There’s currently no built-in Dify config or SQLAlchemy engine option in the codebase to set the isolation level for all MySQL sessions automatically—you’d need to set it manually for each session, as you’ve done, or patch session creation to always run SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED (see source). You could also try setting the isolation level globally at the MySQL server level, but this affects all connections and may have side effects for concurrent workflows.

Best practice is to keep insert and query operations in the same session if possible, or use a utility/wrapper to set the isolation level for sessions that need immediate visibility. If you want a more elegant solution, you could subclass SQLAlchemy’s Session or use an event listener to set the isolation level automatically for each new session.

Let me know if you want a sample implementation for a session wrapper or event listener!

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 (Dec 1, 2025): <!-- Answer --> This happens because MySQL’s default isolation level is REPEATABLE READ, so a new session may not immediately see rows committed by another session. Manually setting the isolation level to READ COMMITTED per session works, but it’s not elegant and Dify doesn’t configure this globally by default. There’s currently no built-in Dify config or SQLAlchemy engine option in the codebase to set the isolation level for all MySQL sessions automatically—you’d need to set it manually for each session, as you’ve done, or patch session creation to always run `SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED` (see [source](https://github.com/langgenius/dify/blob/e8f93380d1e260017f2483c5f410a5cfb0a0219c/api/configs/middleware/__init__.py#L107-L232)). You could also try setting the isolation level globally at the MySQL server level, but this affects all connections and may have side effects for concurrent workflows. Best practice is to keep insert and query operations in the same session if possible, or use a utility/wrapper to set the isolation level for sessions that need immediate visibility. If you want a more elegant solution, you could subclass SQLAlchemy’s Session or use an event listener to set the isolation level automatically for each new session. Let me know if you want a sample implementation for a session wrapper or event listener! <!-- 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/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?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=This%20happens%20because%20MySQL%E2%80%99s%20default%20isolation%20level%20is%20REPEATABLE%20READ%2C%20so%20a%20new%20session%20may%20not%20immediately%20see%20rows%20committed%20by%20another%20session.%20Manually%20setting%20the%20isolation%20level%20to%20READ%20COMMITTED%20per%20session%20works%2C%20but%20it%E2%80%99s%20not%20elegant%20and%20Dify%20doesn%E2%80%99t%20configure%20this%20globally%20by%20default.%0A%0AThere%E2%80%99s%20currently%20no%20built-in%20Dify%20config%20or%20SQLAlchemy%20engine%20option%20in%20the%20codebase%20to%20set%20the%20isolation%20level%20for%20all%20MySQL%20sessions%20automatically%E2%80%94you%E2%80%99d%20need%20to%20set%20it%20manually%20for%20each%20session%2C%20as%20you%E2%80%99ve%20done%2C%20or%20patch%20session%20creation%20to%20always%20run%20%60SET%20SESSION%20TRANSACTION%20ISOLATION%20LEVEL%20READ%20COMMITTED%60%20%28see%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/e8f93380d1e260017f2483c5f410a5cfb0a0219c/api/configs/middleware/__init__.py%23L107-L232%29%29.%20You%20could%20also%20try%20setting%20the%20isolation%20level%20globally%20at%20the%20MySQL%20server%20level%2C%20but%20this%20affects%20all%20connections%20and%20may%20have%20side%20effects%20for%20concurrent%20workflows.%0A%0ABest%20practice%20is%20to%20keep%20insert%20and%20query%20operations%20in%20the%20same%20session%20if%20possible%2C%20or%20use%20a%20utility/wrapper%20to%20set%20the%20isolation%20level%20for%20sessions%20that%20need%20immediate%20visibility.%20If%20you%20want%20a%20more%20elegant%20solution%2C%20you%20could%20subclass%20SQLAlchemy%E2%80%99s%20Session%20or%20use%20an%20event%20listener%20to%20set%20the%20isolation%20level%20automatically%20for%20each%20new%20session.%0A%0ALet%20me%20know%20if%20you%20want%20a%20sample%20implementation%20for%20a%20session%20wrapper%20or%20event%20listener%21)&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/28999)
Author
Owner

@batscars commented on GitHub (Dec 1, 2025):

@dosu

This happens because MySQL’s default isolation level is REPEATABLE READ, so a new session may not immediately see rows committed by another session. Manually setting the isolation level to READ COMMITTED per session works, but it’s not elegant and Dify doesn’t configure this globally by default.

There’s currently no built-in Dify config or SQLAlchemy engine option in the codebase to set the isolation level for all MySQL sessions automatically—you’d need to set it manually for each session, as you’ve done, or patch session creation to always run SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED (see source). You could also try setting the isolation level globally at the MySQL server level, but this affects all connections and may have side effects for concurrent workflows.

Best practice is to keep insert and query operations in the same session if possible, or use a utility/wrapper to set the isolation level for sessions that need immediate visibility. If you want a more elegant solution, you could subclass SQLAlchemy’s Session or use an event listener to set the isolation level automatically for each new session.

Let me know if you want a sample implementation for a session wrapper or event listener!

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

use a utility/wrapper to set the isolation level for sessions that need immediate visibility. If you want a more elegant solution, you could subclass SQLAlchemy’s Session or use an event listener to set the isolation level automatically for each new session.

give me sample code @dosu

@batscars commented on GitHub (Dec 1, 2025): @dosu > This happens because MySQL’s default isolation level is REPEATABLE READ, so a new session may not immediately see rows committed by another session. Manually setting the isolation level to READ COMMITTED per session works, but it’s not elegant and Dify doesn’t configure this globally by default. > > There’s currently no built-in Dify config or SQLAlchemy engine option in the codebase to set the isolation level for all MySQL sessions automatically—you’d need to set it manually for each session, as you’ve done, or patch session creation to always run `SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED` (see [source](https://github.com/langgenius/dify/blob/e8f93380d1e260017f2483c5f410a5cfb0a0219c/api/configs/middleware/__init__.py#L107-L232)). You could also try setting the isolation level globally at the MySQL server level, but this affects all connections and may have side effects for concurrent workflows. > > Best practice is to keep insert and query operations in the same session if possible, or use a utility/wrapper to set the isolation level for sessions that need immediate visibility. If you want a more elegant solution, you could subclass SQLAlchemy’s Session or use an event listener to set the isolation level automatically for each new session. > > Let me know if you want a sample implementation for a session wrapper or event listener! > > _To reply, just mention [@dosu](https://go.dosu.dev/dosubot)._ > > How did I do? [Good](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/8e110361-dd80-46d0-90f4-44c95e8af649?feedback_type=other) > > [![Chat with Dosu](https://camo.githubusercontent.com/7c571478962a6b8a5d47cac74b6824c75e4f6731bba52377e6007f9150462923/68747470733a2f2f646f73752e6465762f646f73752d636861742d62616467652e737667)](https://app.dosu.dev/6088a4f4-073a-43f3-b3d4-4f06fb0c05a0/ask?utm_source=github) [![Open in Cursor](https://camo.githubusercontent.com/bdf7dbded65ee585887f47e5fd6fa099ea0933088b4b03d02e83b4def50154d4/68747470733a2f2f646f73752e6465762f646f73752d696e2d637572736f722e737667)](https://cursor.com/link/prompt?text=This%20happens%20because%20MySQL%E2%80%99s%20default%20isolation%20level%20is%20REPEATABLE%20READ%2C%20so%20a%20new%20session%20may%20not%20immediately%20see%20rows%20committed%20by%20another%20session.%20Manually%20setting%20the%20isolation%20level%20to%20READ%20COMMITTED%20per%20session%20works%2C%20but%20it%E2%80%99s%20not%20elegant%20and%20Dify%20doesn%E2%80%99t%20configure%20this%20globally%20by%20default.%0A%0AThere%E2%80%99s%20currently%20no%20built-in%20Dify%20config%20or%20SQLAlchemy%20engine%20option%20in%20the%20codebase%20to%20set%20the%20isolation%20level%20for%20all%20MySQL%20sessions%20automatically%E2%80%94you%E2%80%99d%20need%20to%20set%20it%20manually%20for%20each%20session%2C%20as%20you%E2%80%99ve%20done%2C%20or%20patch%20session%20creation%20to%20always%20run%20%60SET%20SESSION%20TRANSACTION%20ISOLATION%20LEVEL%20READ%20COMMITTED%60%20%28see%20%5Bsource%5D%28https%3A//github.com/langgenius/dify/blob/e8f93380d1e260017f2483c5f410a5cfb0a0219c/api/configs/middleware/__init__.py%23L107-L232%29%29.%20You%20could%20also%20try%20setting%20the%20isolation%20level%20globally%20at%20the%20MySQL%20server%20level%2C%20but%20this%20affects%20all%20connections%20and%20may%20have%20side%20effects%20for%20concurrent%20workflows.%0A%0ABest%20practice%20is%20to%20keep%20insert%20and%20query%20operations%20in%20the%20same%20session%20if%20possible%2C%20or%20use%20a%20utility/wrapper%20to%20set%20the%20isolation%20level%20for%20sessions%20that%20need%20immediate%20visibility.%20If%20you%20want%20a%20more%20elegant%20solution%2C%20you%20could%20subclass%20SQLAlchemy%E2%80%99s%20Session%20or%20use%20an%20event%20listener%20to%20set%20the%20isolation%20level%20automatically%20for%20each%20new%20session.%0A%0ALet%20me%20know%20if%20you%20want%20a%20sample%20implementation%20for%20a%20session%20wrapper%20or%20event%20listener%21) [![Join Discord](https://camo.githubusercontent.com/7d2066700925db1e370d956834f9ea0e5bc92cecbe84963fbd2a363e45091b4e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6a6f696e2d3538363546323f6c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465266c6162656c3d)](https://go.dosu.dev/discord-bot) [![Share on X](https://camo.githubusercontent.com/a8bd7f3fcf3f5e3bd124eee9ae50ae2ac17b40971726665ac2121d48f9aee155/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f582d73686172652d626c61636b)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/langgenius/dify/issues/28999) use a utility/wrapper to set the isolation level for sessions that need immediate visibility. If you want a more elegant solution, you could subclass SQLAlchemy’s Session or use an event listener to set the isolation level automatically for each new session. give me sample code @dosu
Author
Owner

@dosubot[bot] commented on GitHub (Dec 1, 2025):

The cleanest way to set the isolation level for every new SQLAlchemy session in MySQL is to use an event listener. This ensures every session starts with READ COMMITTED without manual SQL in your business logic.

Here’s a sample you can add to your app initialization (e.g., right after you create your SQLAlchemy engine):

from sqlalchemy import event, text
from sqlalchemy.engine import Engine

# Attach this only if using MySQL
@event.listens_for(Engine, "connect")
def set_mysql_isolation_level(dbapi_connection, connection_record):
    cursor = dbapi_connection.cursor()
    cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED")
    cursor.close()
  • Place this code in your main app setup, after your engine is created but before you start using sessions.
  • This will run for every new DBAPI connection (i.e., every new connection from the pool).
  • It’s safe with SQLAlchemy’s connection pooling and works with both mysqlclient and pymysql.

To verify, you can run SELECT @@session.tx_isolation (MySQL <8.0) or SELECT @@session.transaction_isolation (MySQL 8.0+) in a session and confirm it returns READ-COMMITTED.

This approach is widely used and recommended for SQLAlchemy + MySQL. No need to subclass Session or wrap every session manually.

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 (Dec 1, 2025): <!-- Answer --> The cleanest way to set the isolation level for every new SQLAlchemy session in MySQL is to use an event listener. This ensures every session starts with `READ COMMITTED` without manual SQL in your business logic. Here’s a sample you can add to your app initialization (e.g., right after you create your SQLAlchemy engine): ```python from sqlalchemy import event, text from sqlalchemy.engine import Engine # Attach this only if using MySQL @event.listens_for(Engine, "connect") def set_mysql_isolation_level(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() cursor.execute("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED") cursor.close() ``` - Place this code in your main app setup, after your engine is created but before you start using sessions. - This will run for every new DBAPI connection (i.e., every new connection from the pool). - It’s safe with SQLAlchemy’s connection pooling and works with both `mysqlclient` and `pymysql`. To verify, you can run `SELECT @@session.tx_isolation` (MySQL <8.0) or `SELECT @@session.transaction_isolation` (MySQL 8.0+) in a session and confirm it returns `READ-COMMITTED`. This approach is widely used and recommended for SQLAlchemy + MySQL. No need to subclass Session or wrap every session manually. <!-- 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/be956332-3235-43ea-86e9-7425d34f54dd?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/be956332-3235-43ea-86e9-7425d34f54dd?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/be956332-3235-43ea-86e9-7425d34f54dd?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/be956332-3235-43ea-86e9-7425d34f54dd?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/be956332-3235-43ea-86e9-7425d34f54dd?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/be956332-3235-43ea-86e9-7425d34f54dd?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/be956332-3235-43ea-86e9-7425d34f54dd?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%20cleanest%20way%20to%20set%20the%20isolation%20level%20for%20every%20new%20SQLAlchemy%20session%20in%20MySQL%20is%20to%20use%20an%20event%20listener.%20This%20ensures%20every%20session%20starts%20with%20%60READ%20COMMITTED%60%20without%20manual%20SQL%20in%20your%20business%20logic.%0A%0AHere%E2%80%99s%20a%20sample%20you%20can%20add%20to%20your%20app%20initialization%20%28e.g.%2C%20right%20after%20you%20create%20your%20SQLAlchemy%20engine%29%3A%0A%0A%60%60%60python%0Afrom%20sqlalchemy%20import%20event%2C%20text%0Afrom%20sqlalchemy.engine%20import%20Engine%0A%0A%23%20Attach%20this%20only%20if%20using%20MySQL%0A%40event.listens_for%28Engine%2C%20%22connect%22%29%0Adef%20set_mysql_isolation_level%28dbapi_connection%2C%20connection_record%29%3A%0A%20%20%20%20cursor%20%3D%20dbapi_connection.cursor%28%29%0A%20%20%20%20cursor.execute%28%22SET%20SESSION%20TRANSACTION%20ISOLATION%20LEVEL%20READ%20COMMITTED%22%29%0A%20%20%20%20cursor.close%28%29%0A%60%60%60%0A%0A-%20Place%20this%20code%20in%20your%20main%20app%20setup%2C%20after%20your%20engine%20is%20created%20but%20before%20you%20start%20using%20sessions.%0A-%20This%20will%20run%20for%20every%20new%20DBAPI%20connection%20%28i.e.%2C%20every%20new%20connection%20from%20the%20pool%29.%0A-%20It%E2%80%99s%20safe%20with%20SQLAlchemy%E2%80%99s%20connection%20pooling%20and%20works%20with%20both%20%60mysqlclient%60%20and%20%60pymysql%60.%0A%0ATo%20verify%2C%20you%20can%20run%20%60SELECT%20%40%40session.tx_isolation%60%20%28MySQL%20%3C8.0%29%20or%20%60SELECT%20%40%40session.transaction_isolation%60%20%28MySQL%208.0%2B%29%20in%20a%20session%20and%20confirm%20it%20returns%20%60READ-COMMITTED%60.%0A%0AThis%20approach%20is%20widely%20used%20and%20recommended%20for%20SQLAlchemy%20%2B%20MySQL.%20No%20need%20to%20subclass%20Session%20or%20wrap%20every%20session%20manually.)&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/28999)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#20725