mirror of
https://github.com/open-webui/open-webui.git
synced 2026-06-09 11:45:57 -05:00
[GH-ISSUE #23854] issue: v0.9.0 (:dev): DATABASE_URL SSL regression — asyncpg and peewee/psycopg2 require incompatible query-string keys #20089
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @jaco5842 on GitHub (Apr 17, 2026).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/23854
Check Existing Issues
Installation Method
Docker
Open WebUI Version
v0.9.0 (:dev branch)
Ollama Version (if applicable)
No response
Operating System
Windows 11 Pro, Docker Desktop with WSL2 backend. Container: official open-webui:dev image (Python 3.11).
Browser (if applicable)
No response
Confirmation
README.md.Expected Behavior
Open WebUI starts cleanly when DATABASE_URL points at an SSL-required Postgres (Azure Database for PostgreSQL, AWS RDS, Supabase, DigitalOcean managed PG, etc.) using
?sslmode=require— the syntax thatworked in every prior release and is documented by libpq / psycopg2.
Actual Behavior
Reporting per the project's guidance that bugs reproduced on the :dev branch should be filed as issues. Reproduced on
ghcr.io/open-webui/open-webui:dev(v0.9.0, current as of 2026-04-17).Startup crashes before serving any request, with a mutually exclusive choice of errors depending on which SSL query-string parameter is used in DATABASE_URL. Neither value satisfies both drivers that v0.9.0
now uses concurrently:
?sslmode=require→ asyncpg raisesTypeError: connect() got an unexpected keyword argument 'sslmode'(SQLAlchemy/asyncpg runtime path).?ssl=require→ psycopg2 raisespsycopg2.ProgrammingError: invalid dsn: invalid connection option "ssl"(peewee migration path inopen_webui/internal/db.py:66).v0.9 appears to have added an async SQLAlchemy + asyncpg runtime path alongside the existing peewee + psycopg2 migration path. The two drivers parse DSN query strings differently:
sslmode.ssl; rejectssslmodeas an unknown kwarg.No single
DATABASE_URLvalue works for both drivers, so any deployment requiring SSL fails at startup. Earlier versions (v0.8.x) only used psycopg2 and accepted?sslmode=requirewithout issue, so this isa regression for every managed-Postgres user.
Workaround (undocumented): remove the SSL query string from
DATABASE_URLentirely and setPGSSLMODE=requireas a separate environment variable. Both drivers honor libpq'sPGSSLMODEenv var as afallback, so this satisfies both paths.
Steps to Reproduce
Start with a clean Docker Desktop install (tested on Windows 11 Pro + WSL2, but OS is not relevant — same issue on Linux hosts).
Provision any managed Postgres that requires SSL (verified against Azure Database for PostgreSQL Flexible Server; same applies to AWS RDS, Supabase, etc.).
Create an empty database and a user with CREATE privileges on it.
Create a
docker-compose.yml:Logs & Screenshots
❯ 2026-04-17 23:30:00.675 | Failed to initialize the database connection: invalid dsn: invalid connection option "ssl"
2026-04-17 23:30:00.675 |
2026-04-17 23:30:00.676 | Hint: If your database password contains special characters, you may need to URL-encode it.
2026-04-17 23:30:00.676 | Traceback (most recent call last):
2026-04-17 23:30:00.676 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3263, in connect
2026-04-17 23:30:00.677 | self._state.set_connection(self._connect())
2026-04-17 23:30:00.677 | ^^^^^^^^^^^^^^^
2026-04-17 23:30:00.677 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 4001, in _connect
2026-04-17 23:30:00.677 | conn = psycopg2.connect(**params)
2026-04-17 23:30:00.677 | ^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-17 23:30:00.677 | File "/usr/local/lib/python3.11/site-packages/psycopg2/init.py", line 121, in connect
2026-04-17 23:30:00.677 | dsn = _ext.make_dsn(dsn, **kwargs)
2026-04-17 23:30:00.677 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-17 23:30:00.677 | File "/usr/local/lib/python3.11/site-packages/psycopg2/extensions.py", line 167, in make_dsn
2026-04-17 23:30:00.677 | parse_dsn(dsn)
2026-04-17 23:30:00.677 | psycopg2.ProgrammingError: invalid dsn: invalid connection option "ssl"
2026-04-17 23:30:00.677 |
2026-04-17 23:30:00.677 |
2026-04-17 23:30:00.677 | During handling of the above exception, another exception occurred:
2026-04-17 23:30:00.677 |
2026-04-17 23:30:00.677 | Traceback (most recent call last):
2026-04-17 23:30:00.677 | File "/app/backend/open_webui/internal/db.py", line 66, in handle_peewee_migration
2026-04-17 23:30:00.677 | db = register_connection(DATABASE_URL.replace('postgresql://', 'postgres://'))
2026-04-17 23:30:00.677 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-17 23:30:00.677 | File "/app/backend/open_webui/internal/wrappers.py", line 76, in register_connection
2026-04-17 23:30:00.677 | db.connect(reuse_if_open=True)
2026-04-17 23:30:00.677 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3262, in connect
2026-04-17 23:30:00.678 | with exception_wrapper:
2026-04-17 23:30:00.678 | File "/usr/local/lib/python3.11/site-packages/peewee.py", line 3088, in exit
2026-04-17 23:30:00.678 | reraise(new_type, new_type(exc_value, *exc_args), traceback)
2026-04-17 23:30:00.678 | File "/usr/local/lib/python3.11/site-pac
──── (380 lines hidden) ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
m_string
2026-04-17 23:30:07.962 | module = importlib.import_module(module_str)
2026-04-17 23:30:07.962 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-17 23:30:07.962 | File "/usr/local/lib/python3.11/importlib/init.py", line 126, in import_module
2026-04-17 23:30:07.962 | return _bootstrap._gcd_import(name[level:], package, level)
2026-04-17 23:30:07.962 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2026-04-17 23:30:07.962 | File "", line 1204, in _gcd_import
2026-04-17 23:30:07.962 | File "", line 1176, in _find_and_load
2026-04-17 23:30:07.962 | File "", line 1147, in _find_and_load_unlocked
2026-04-17 23:30:07.962 | File "", line 690, in _load_unlocked
2026-04-17 23:30:07.962 | File "", line 940, in exec_module
2026-04-17 23:30:07.962 | File "", line 241, in _call_with_frames_removed
2026-04-17 23:30:07.962 | File "/app/backend/open_webui/main.py", line 60, in
2026-04-17 23:30:07.963 | from open_webui.utils.asgi_middleware import (
2026-04-17 23:30:07.963 | File "/app/backend/open_webui/utils/asgi_middleware.py", line 44, in
2026-04-17 23:30:07.963 | from open_webui.internal.db import ScopedSession
2026-04-17 23:30:07.963 | File "/app/backend/open_webui/internal/db.py", line 86, in
2026-04-17 23:30:07.963 | handle_peewee_migration(DATABASE_URL)
2026-04-17 23:30:07.963 | File "/app/backend/open_webui/internal/db.py", line 78, in handle_peewee_migration
2026-04-17 23:30:07.963 | if db and not db.is_closed():
2026-04-17 23:30:07.963 | ^^
Additional Information
Root cause summary: v0.9 added an async SQLAlchemy + asyncpg code path for runtime queries (open_webui/models/functions.py, etc.) while retaining the peewee + psycopg2 path for migrations
(open_webui/internal/db.py:handle_peewee_migration). Both drivers parse
DATABASE_URLindependently, and their query-string conventions for SSL are incompatible (sslmodevsssl). No documentation coversthe new requirement.
Suggested fixes (pick any one, or combine):
PGSSLMODE=requireas an env var and omit the SSL query string from DATABASE_URL.sslmode/sslfrom the URL and inject the right kwarg per driver.sslmode=<value>→ asyncpgconnect_args={"ssl": <value>}at the SQLAlchemy engine setup site, so the libpq-style URL keeps working.Secondary cleanup: in
open_webui/internal/db.py:handle_peewee_migration, initializedb = Noneat the top of the function so the outerif db and not db.is_closed()doesn't fail withUnboundLocalErrorwhen the connect itself raises. Right now the real error is masked by a NameError.
Confirmed affected configurations: Azure Database for PostgreSQL Flexible Server (SSL required by default, cannot be disabled). Same failure pattern is expected on AWS RDS, DigitalOcean Managed PG, Supabase,
etc., since all require SSL.