[PR #9080] [CLOSED] fix: Make sure handle_peewee_migration doesn't throw on connection error #9109

Closed
opened 2025-11-11 18:14:21 -06:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/open-webui/open-webui/pull/9080
Author: @Kami
Created: 1/29/2025
Status: Closed

Base: devHead: fix/database-connection-error-fix


📝 Commits (1)

  • 3f3d6d7 fix: Make sure db is initialized to None otherwise it will fail in

📊 Changes

1 file changed (+3 additions, -2 deletions)

View changed files

📝 backend/open_webui/internal/db.py (+3 -2)

📄 Description

Description

This pull request updates handle_peewee_migration function so it doesn't throw UnboundLocalError in case code in the main try: block throws an exception.

This can happen in case the database is down, DNS name can't be resolved or any other connection related error.

Background, Context

I noticed this issue when running Open WebUI locally when docker networking was misconfiguration so the application server couldn't reach the database (PostgreSQL in my case).

Here is the full exception from the logs:

openwebui-1  | Failed to initialize the database connection: could not translate host name "database" to address: Name or service not known
openwebui-1  | 
openwebui-1  | Traceback (most recent call last):
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3263, in connect
openwebui-1  | /app/backend/open_webui
openwebui-1  | /app/backend
openwebui-1  | /app
openwebui-1  |     self._state.set_connection(self._connect())
openwebui-1  |                                ^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 4001, in _connect
openwebui-1  |     conn = psycopg2.connect(**params)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect
openwebui-1  |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  | psycopg2.OperationalError: could not translate host name "database" to address: Name or service not known
openwebui-1  | 
openwebui-1  | 
openwebui-1  | During handling of the above exception, another exception occurred:
openwebui-1  | 
openwebui-1  | Traceback (most recent call last):
openwebui-1  |   File "/app/backend/open_webui/internal/db.py", line 57, in handle_peewee_migration
openwebui-1  |     db = register_connection(DATABASE_URL.replace("postgresql://", "postgres://"))
openwebui-1  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/app/backend/open_webui/internal/wrappers.py", line 58, in register_connection
openwebui-1  |     db.connect(reuse_if_open=True)
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3262, in connect
openwebui-1  |     with __exception_wrapper__:
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3088, in __exit__
openwebui-1  |     reraise(new_type, new_type(exc_value, *exc_args), traceback)
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 196, in reraise
openwebui-1  |     raise value.with_traceback(tb)
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3263, in connect
openwebui-1  |     self._state.set_connection(self._connect())
openwebui-1  |                                ^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/peewee.py", line 4001, in _connect
openwebui-1  |     conn = psycopg2.connect(**params)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect
openwebui-1  |     conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  | peewee.OperationalError: could not translate host name "database" to address: Name or service not known
openwebui-1  | 
openwebui-1  | 
openwebui-1  | During handling of the above exception, another exception occurred:
openwebui-1  | 
openwebui-1  | Traceback (most recent call last):
openwebui-1  |   File "/usr/local/bin/uvicorn", line 10, in <module>
openwebui-1  |     sys.exit(main())
openwebui-1  |              ^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1161, in __call__
openwebui-1  |     return self.main(*args, **kwargs)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1082, in main
openwebui-1  |     rv = self.invoke(ctx)
openwebui-1  |          ^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1443, in invoke
openwebui-1  |     return ctx.invoke(self.callback, **ctx.params)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/click/core.py", line 788, in invoke
openwebui-1  |     return __callback(*args, **kwargs)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 410, in main
openwebui-1  |     run(
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 577, in run
openwebui-1  |     server.run()
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 65, in run
openwebui-1  |     return asyncio.run(self.serve(sockets=sockets))
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run
openwebui-1  |     return runner.run(main)
openwebui-1  |            ^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run
openwebui-1  |     return self._loop.run_until_complete(task)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 69, in serve
openwebui-1  |     await self._serve(sockets)
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 76, in _serve
openwebui-1  |     config.load()
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 434, in load
openwebui-1  |     self.loaded_app = import_from_string(self.app)
openwebui-1  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 19, in import_from_string
openwebui-1  |     module = importlib.import_module(module_str)
openwebui-1  |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module
openwebui-1  |     return _bootstrap._gcd_import(name[level:], package, level)
openwebui-1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
openwebui-1  |   File "<frozen importlib._bootstrap>", line 1204, in _gcd_import
openwebui-1  |   File "<frozen importlib._bootstrap>", line 1176, in _find_and_load
openwebui-1  |   File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked
openwebui-1  |   File "<frozen importlib._bootstrap>", line 690, in _load_unlocked
openwebui-1  |   File "<frozen importlib._bootstrap_external>", line 940, in exec_module
openwebui-1  |   File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
openwebui-1  |   File "/app/backend/open_webui/main.py", line 48, in <module>
openwebui-1  |     from open_webui.socket.main import (
openwebui-1  |   File "/app/backend/open_webui/socket/main.py", line 7, in <module>
openwebui-1  |     from open_webui.models.users import Users, UserNameResponse
openwebui-1  |   File "/app/backend/open_webui/models/users.py", line 4, in <module>
openwebui-1  |     from open_webui.internal.db import Base, JSONField, get_db
openwebui-1  |   File "/app/backend/open_webui/internal/db.py", line 75, in <module>
openwebui-1  |     handle_peewee_migration(DATABASE_URL)
openwebui-1  |   File "/app/backend/open_webui/internal/db.py", line 68, in handle_peewee_migration
openwebui-1  |     if db and not db.is_closed():
openwebui-1  |        ^^
openwebui-1  | UnboundLocalError: cannot access local variable 'db' where it is not associated with a value

Proposed Implementation / Fix

Fix is simple. I make sure db is initialized to None at the beginning of the function (before the try block). This way inside finally block we don't try to close the connection in case the variable is not initialized.

It looks like this code was originally introduced in d3d161f723 by @tjbck, but since there is no code comment or commit description, is not clear to me why that line was originally commented out.

Notes

I imagine static analysis tool such as pylint should catch such issues. It looks like like GHA workflow (.github/workflows/lint-backend.disabled) is disabled. It appears that was done in ea7ea52ba3.

If there is no special reason (e.g. too many false positives), it would be a good idea to enable it so it automatically catches minor issues and bugs like this one.

Testing

So far I only tested the change locally end to end manually, but when I get a chance and become more familiar with the development environment, I will work on adding some tests for it.

TODO

  • Add some (unit?) tests for it
  • Update changelog

Other

Thanks to everyone who is contributed or contributed to this project and made it possible.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/open-webui/open-webui/pull/9080 **Author:** [@Kami](https://github.com/Kami) **Created:** 1/29/2025 **Status:** ❌ Closed **Base:** `dev` ← **Head:** `fix/database-connection-error-fix` --- ### 📝 Commits (1) - [`3f3d6d7`](https://github.com/open-webui/open-webui/commit/3f3d6d70caafbb16e3bbd23f16d528c08bcf4489) fix: Make sure db is initialized to None otherwise it will fail in ### 📊 Changes **1 file changed** (+3 additions, -2 deletions) <details> <summary>View changed files</summary> 📝 `backend/open_webui/internal/db.py` (+3 -2) </details> ### 📄 Description ## Description This pull request updates `handle_peewee_migration` function so it doesn't throw `UnboundLocalError` in case code in the main `try:` block throws an exception. This can happen in case the database is down, DNS name can't be resolved or any other connection related error. ## Background, Context I noticed this issue when running Open WebUI locally when docker networking was misconfiguration so the application server couldn't reach the database (PostgreSQL in my case). Here is the full exception from the logs: ```bash openwebui-1 | Failed to initialize the database connection: could not translate host name "database" to address: Name or service not known openwebui-1 | openwebui-1 | Traceback (most recent call last): openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3263, in connect openwebui-1 | /app/backend/open_webui openwebui-1 | /app/backend openwebui-1 | /app openwebui-1 | self._state.set_connection(self._connect()) openwebui-1 | ^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 4001, in _connect openwebui-1 | conn = psycopg2.connect(**params) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect openwebui-1 | conn = _connect(dsn, connection_factory=connection_factory, **kwasync) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | psycopg2.OperationalError: could not translate host name "database" to address: Name or service not known openwebui-1 | openwebui-1 | openwebui-1 | During handling of the above exception, another exception occurred: openwebui-1 | openwebui-1 | Traceback (most recent call last): openwebui-1 | File "/app/backend/open_webui/internal/db.py", line 57, in handle_peewee_migration openwebui-1 | db = register_connection(DATABASE_URL.replace("postgresql://", "postgres://")) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/app/backend/open_webui/internal/wrappers.py", line 58, in register_connection openwebui-1 | db.connect(reuse_if_open=True) openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3262, in connect openwebui-1 | with __exception_wrapper__: openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3088, in __exit__ openwebui-1 | reraise(new_type, new_type(exc_value, *exc_args), traceback) openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 196, in reraise openwebui-1 | raise value.with_traceback(tb) openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3263, in connect openwebui-1 | self._state.set_connection(self._connect()) openwebui-1 | ^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 4001, in _connect openwebui-1 | conn = psycopg2.connect(**params) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/psycopg2/__init__.py", line 122, in connect openwebui-1 | conn = _connect(dsn, connection_factory=connection_factory, **kwasync) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | peewee.OperationalError: could not translate host name "database" to address: Name or service not known openwebui-1 | openwebui-1 | openwebui-1 | During handling of the above exception, another exception occurred: openwebui-1 | openwebui-1 | Traceback (most recent call last): openwebui-1 | File "/usr/local/bin/uvicorn", line 10, in <module> openwebui-1 | sys.exit(main()) openwebui-1 | ^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1161, in __call__ openwebui-1 | return self.main(*args, **kwargs) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1082, in main openwebui-1 | rv = self.invoke(ctx) openwebui-1 | ^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/click/core.py", line 1443, in invoke openwebui-1 | return ctx.invoke(self.callback, **ctx.params) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/click/core.py", line 788, in invoke openwebui-1 | return __callback(*args, **kwargs) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 410, in main openwebui-1 | run( openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/main.py", line 577, in run openwebui-1 | server.run() openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 65, in run openwebui-1 | return asyncio.run(self.serve(sockets=sockets)) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/asyncio/runners.py", line 190, in run openwebui-1 | return runner.run(main) openwebui-1 | ^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/asyncio/runners.py", line 118, in run openwebui-1 | return self._loop.run_until_complete(task) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "uvloop/loop.pyx", line 1518, in uvloop.loop.Loop.run_until_complete openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 69, in serve openwebui-1 | await self._serve(sockets) openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/server.py", line 76, in _serve openwebui-1 | config.load() openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/config.py", line 434, in load openwebui-1 | self.loaded_app = import_from_string(self.app) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/site-packages/uvicorn/importer.py", line 19, in import_from_string openwebui-1 | module = importlib.import_module(module_str) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "/usr/local/lib/python3.11/importlib/__init__.py", line 126, in import_module openwebui-1 | return _bootstrap._gcd_import(name[level:], package, level) openwebui-1 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ openwebui-1 | File "<frozen importlib._bootstrap>", line 1204, in _gcd_import openwebui-1 | File "<frozen importlib._bootstrap>", line 1176, in _find_and_load openwebui-1 | File "<frozen importlib._bootstrap>", line 1147, in _find_and_load_unlocked openwebui-1 | File "<frozen importlib._bootstrap>", line 690, in _load_unlocked openwebui-1 | File "<frozen importlib._bootstrap_external>", line 940, in exec_module openwebui-1 | File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed openwebui-1 | File "/app/backend/open_webui/main.py", line 48, in <module> openwebui-1 | from open_webui.socket.main import ( openwebui-1 | File "/app/backend/open_webui/socket/main.py", line 7, in <module> openwebui-1 | from open_webui.models.users import Users, UserNameResponse openwebui-1 | File "/app/backend/open_webui/models/users.py", line 4, in <module> openwebui-1 | from open_webui.internal.db import Base, JSONField, get_db openwebui-1 | File "/app/backend/open_webui/internal/db.py", line 75, in <module> openwebui-1 | handle_peewee_migration(DATABASE_URL) openwebui-1 | File "/app/backend/open_webui/internal/db.py", line 68, in handle_peewee_migration openwebui-1 | if db and not db.is_closed(): openwebui-1 | ^^ openwebui-1 | UnboundLocalError: cannot access local variable 'db' where it is not associated with a value ``` ## Proposed Implementation / Fix Fix is simple. I make sure `db` is initialized to `None` at the beginning of the function (before the `try` block). This way inside `finally` block we don't try to close the connection in case the variable is not initialized. It looks like this code was originally introduced in d3d161f723e8667e236510c198cf6b194c04e118 by @tjbck, but since there is no code comment or commit description, is not clear to me why that line was originally commented out. ## Notes I imagine static analysis tool such as `pylint` should catch such issues. It looks like like GHA workflow (`.github/workflows/lint-backend.disabled`) is disabled. It appears that was done in ea7ea52ba386c77c35a495c716394609600ca67e. If there is no special reason (e.g. too many false positives), it would be a good idea to enable it so it automatically catches minor issues and bugs like this one. ## Testing So far I only tested the change locally end to end manually, but when I get a chance and become more familiar with the development environment, I will work on adding some tests for it. ## TODO - [ ] Add some (unit?) tests for it - [ ] Update changelog ## Other Thanks to everyone who is contributed or contributed to this project and made it possible. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2025-11-11 18:14:21 -06:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/open-webui#9109