[GH-ISSUE #14081] issue: postgresql backend ? #136860

Closed
opened 2026-05-25 05:35:58 -05:00 by GiteaMirror · 0 comments
Owner

Originally created by @erenirmak on GitHub (May 20, 2025).
Original GitHub issue: https://github.com/open-webui/open-webui/issues/14081

Check Existing Issues

  • I have searched the existing issues and discussions.
  • I am using the latest version of Open WebUI.

Installation Method

Pip Install

Open WebUI Version

0.6.10

Ollama Version (if applicable)

No response

Operating System

Windows

Browser (if applicable)

No response

Confirmation

  • I have read and followed all instructions in README.md.
  • I am using the latest version of both Open WebUI and Ollama.
  • I have included the browser console logs.
  • I have included the Docker container logs.
  • I have listed steps to reproduce the bug in detail.

Expected Behavior

I defined DATABASE_URL env to be able to postgresql as a backend. tables should be created in the database.

Actual Behavior

It says:

Failed to initialize the database connection: Unrecognized or unsupported scheme: "postgresql+psycopg2".

Steps to Reproduce

  1. created dockerfile. using python:3.12.10 image. Installing some libraries besides open-webui.

Complete Dockerfile:

FROM python:3.12.10

WORKDIR /app

COPY requirements.txt .

RUN pip install --no-cache-dir -r requirements.txt

ENV DATA_DIR=/app/data
ENV ENABLE_OLLAMA_API=True
ENV OLLAMA_BASE_URL=http://10.0.0.30:11434
ENV PHOENIX_COLLECTOR_ENDPOINT=http://10.0.0.1:6006
ENV PHOENIX_PROJECT_NAME=openwebui

EXPOSE 8080

CMD ["open-webui", "serve"]
  1. created docker-compose.yml file. setting some environment variables, as well as other services.

Complete docker-compose.yml file:

services:
  open-webui:
    build: .
    ports:
      - "8080:8080"
    container_name: open-webui
    depends_on:
      - postgres
      - tika
      - playwright
    environment:
      - DATABASE_URL=postgresql+psycopg2://openwebui:openwebui@postgres/postgres
      - CONTENT_EXTRACTION_ENGINE=tika
      - TIKA_SERVER_URL=http://tika:9998/
      - PGVECTOR_DB_URL=postgresql+psycopg2://openwebui:openwebui@postgres/openwebui
      - PDF_EXTRACT_IMAGES=true
      - ENABLE_WEB_SEARCH=true
      - WEB_SEARCH_ENGINE=duckduckgo
      - WEB_LOADER_ENGINE=playwright
      - PLAYWRIGHT_WS_URL=ws://playwright:3000
    volumes:
      - ./data:/app/data

    restart: unless-stopped

  tika:
    image: apache/tika:latest-full
    container_name: tika
    ports:
      - "9998:9998"

    restart: unless-stopped

  postgres:
    image: pgvector/pgvector:0.8.0-pg16
    container_name: postgres
    environment:
      POSTGRES_USER: openwebui
      POSTGRES_PASSWORD: openwebui
      POSTGRES_DB: openwebui
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data

    restart: unless-stopped

  playwright:
    image: mcr.microsoft.com/playwright:v1.49.1-noble
    container_name: playwright
    command: npx -y playwright@1.49.1 run-server --port 3000 --host 0.0.0.0

volumes:
  pgdata:
    driver: local
  1. running "docker compose up -d"

  2. checking logs with "docker logs open-webui"
    it says: "unrecognized schema" error, cannot connect to postgresql database.

P.S. actual values are different. changed them to something generic for convenience.

Logs & Screenshots

user@machine OpenWebUI>docker logs open-webui
Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.
Generating a new secret key and saving it to /app/.webui_secret_key
Loading WEBUI_SECRET_KEY from /app/.webui_secret_key
Failed to initialize the database connection: Unrecognized or unsupported scheme: "postgresql+psycopg2".
/usr/local/lib/python3.12/site-packages/open_webui
/usr/local/lib/python3.12/site-packages
/usr/local/lib/python3.12
╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /usr/local/lib/python3.12/site-packages/open_webui/internal/db.py:57 in │
│ handle_peewee_migration │
│ │
│ 54 │ # db = None │
│ 55 │ try: │
│ 56 │ │ # Replace the postgresql:// with postgres:// to handle the pee │
│ ❱ 57 │ │ db = register_connection(DATABASE_URL.replace("postgresql://", │
│ 58 │ │ migrate_dir = OPEN_WEBUI_DIR / "internal" / "migrations" │
│ 59 │ │ router = Router(db, logger=log, migrate_dir=migrate_dir) │
│ 60 │ │ router.run() │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ DATABASE_URL = 'postgresql+psycopg2://openwebui:openwebui@postgres:5432… │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/internal/wrappers.py:46 │
│ in register_connection │
│ │
│ 43 │
│ 44 │
│ 45 def register_connection(db_url): │
│ ❱ 46 │ db = connect(db_url, unquote_password=True) │
│ 47 │ if isinstance(db, PostgresqlDatabase): │
│ 48 │ │ # Enable autoconnect for SQLite databases, managed by Peewee │
│ 49 │ │ db.autoconnect = True │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ db_url = 'postgresql+psycopg2://openwebui:openwebui@postgres:5432/postg… │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/playhouse/db_url.py:103 in connect │
│ │
│ 100 │ │ │ raise RuntimeError('Attempted to use "%s" but a required l │
│ 101 │ │ │ │ │ │ │ 'could not be imported.' % parsed.schem │
│ 102 │ │ else: │
│ ❱ 103 │ │ │ raise RuntimeError('Unrecognized or unsupported scheme: "% │
│ 104 │ │ │ │ │ │ │ parsed.scheme) │
│ 105 │ │
│ 106 │ return database_class(**connect_kwargs) │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ connect_kwargs = { │ │
│ │ │ 'database': 'postgres', │ │
│ │ │ 'user': 'openwebui', │ │
│ │ │ 'password': 'openwebui', │ │
│ │ │ 'host': 'postgres', │ │
│ │ │ 'port': 5432 │ │
│ │ } │ │
│ │ connect_params = {} │ │
│ │ database_class = None │ │
│ │ parsed = ParseResult( │ │
│ │ │ scheme='postgresql+psycopg2', │ │
│ │ │ netloc='openwebui:openwebui@postgres:5432', │ │
│ │ │ path='/postgres', │ │
│ │ │ params='', │ │
│ │ │ query='', │ │
│ │ │ fragment='' │ │
│ │ ) │ │
│ │ unquote_password = True │ │
│ │ url = 'postgresql+psycopg2://openwebui:openwebui@postgres:… │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────╯
RuntimeError: Unrecognized or unsupported scheme: "postgresql+psycopg2".

During handling of the above exception, another exception occurred:

╭───────────────────── Traceback (most recent call last) ──────────────────────╮
│ /usr/local/lib/python3.12/site-packages/open_webui/__init__.py:75 in serve │
│ │
│ 72 │ │ │ os.environ["USE_CUDA_DOCKER"] = "false" │
│ 73 │ │ │ os.environ["LD_LIBRARY_PATH"] = ":".join(LD_LIBRARY_PATH) │
│ 74 │ │
│ ❱ 75 │ import open_webui.main # we need set environment variables before │
│ 76 │ from open_webui.env import UVICORN_WORKERS # Import the workers s │
│ 77 │ │
│ 78 │ uvicorn.run( │
│ │
│ ╭───── locals ─────╮ │
│ │ host = '0.0.0.0' │ │
│ │ port = 8080 │ │
│ ╰──────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/main.py:50 in │
│ │
│ 47 │
│ 48 │
│ 49 from open_webui.utils import logger │
│ ❱ 50 from open_webui.utils.audit import AuditLevel, AuditLoggingMiddleware │
│ 51 from open_webui.utils.logger import start_logger │
│ 52 from open_webui.socket.main import ( │
│ 53 │ app as socket_app, │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ aiohttp = <module 'aiohttp' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/aiohttp/_init… │ │
│ │ anyio = <module 'anyio' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/anyio/init.… │ │
│ │ applications = <module 'fastapi.applications' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/fastapi/applica… │ │
│ │ asyncio = <module 'asyncio' from │ │
│ │ '/usr/local/lib/python3.12/asyncio/__init__.py'> │ │
│ │ inspect = <module 'inspect' from │ │
│ │ '/usr/local/lib/python3.12/inspect.py'> │ │
│ │ json = <module 'json' from │ │
│ │ '/usr/local/lib/python3.12/json/__init__.py'> │ │
│ │ logger = <module 'open_webui.utils.logger' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/open_webui/util… │ │
│ │ logging = <module 'logging' from │ │
│ │ '/usr/local/lib/python3.12/logging/__init__.py'> │ │
│ │ mimetypes = <module 'mimetypes' from │ │
│ │ '/usr/local/lib/python3.12/mimetypes.py'> │ │
│ │ Optional = typing.Optional │ │
│ │ os = <module 'os' (frozen)> │ │
│ │ random = <module 'random' from │ │
│ │ '/usr/local/lib/python3.12/random.py'> │ │
│ │ requests = <module 'requests' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/requests/__init… │ │
│ │ shutil = <module 'shutil' from │ │
│ │ '/usr/local/lib/python3.12/shutil.py'> │ │
│ │ status = <module 'starlette.status' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/starlette/statu… │ │
│ │ sys = <module 'sys' (built-in)> │ │
│ │ time = <module 'time' (built-in)> │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/utils/audit.py:28 in │
│ │
│ │
│ 25 from starlette.requests import Request │
│ 26 │
│ 27 from open_webui.env import AUDIT_LOG_LEVEL, MAX_BODY_LOG_SIZE │
│ ❱ 28 from open_webui.utils.auth import get_current_user, get_http_authoriza │
│ 29 from open_webui.models.users import UserModel │
│ 30 │
│ 31 │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ ASGI3Application = typing.Callable[[typing.Union[asgiref.typing.HTTP… │ │
│ │ asgiref.typing.WebSocketScope, │ │
│ │ asgiref.typing.LifespanScope], typing.Callable[[], │ │
│ │ typing.Awaitable[typing.Union[asgiref.typing.HTTP… │ │
│ │ asgiref.typing.HTTPDisconnectEvent, │ │
│ │ asgiref.typing.WebSocketConnectEvent, │ │
│ │ asgiref.typing.WebSocketReceiveEvent, │ │
│ │ asgiref.typing.WebSocketDisconnectEvent, │ │
│ │ asgiref.typing.LifespanStartupEvent, │ │
│ │ asgiref.typing.LifespanShutdownEvent]]], │ │
│ │ typing.Callable[[typing.Union[asgiref.typing.HTTP… │ │
│ │ asgiref.typing.HTTPResponseBodyEvent, │ │
│ │ asgiref.typing.HTTPResponseTrailersEvent, │ │
│ │ asgiref.typing.HTTPServerPushEvent, │ │
│ │ asgiref.typing.HTTPDisconnectEvent, │ │
│ │ asgiref.typing.WebSocketAcceptEvent, │ │
│ │ asgiref.typing.WebSocketSendEvent, │ │
│ │ asgiref.typing.WebSocketResponseStartEvent, │ │
│ │ asgiref.typing.WebSocketResponseBodyEvent, │ │
│ │ asgiref.typing.WebSocketCloseEvent, │ │
│ │ asgiref.typing.LifespanStartupCompleteEvent, │ │
│ │ asgiref.typing.LifespanStartupFailedEvent, │ │
│ │ asgiref.typing.LifespanShutdownCompleteEvent, │ │
│ │ asgiref.typing.LifespanShutdownFailedEvent]], │ │
│ │ typing.Awaitable[NoneType]]], │ │
│ │ typing.Awaitable[NoneType]] │ │
│ │ ASGIReceiveCallable = typing.Callable[[], │ │
│ │ typing.Awaitable[typing.Union[asgiref.typing.HTTP… │ │
│ │ asgiref.typing.HTTPDisconnectEvent, │ │
│ │ asgiref.typing.WebSocketConnectEvent, │ │
│ │ asgiref.typing.WebSocketReceiveEvent, │ │
│ │ asgiref.typing.WebSocketDisconnectEvent, │ │
│ │ asgiref.typing.LifespanStartupEvent, │ │
│ │ asgiref.typing.LifespanShutdownEvent]]] │ │
│ │ ASGIReceiveEvent = typing.Union[asgiref.typing.HTTPRequestEvent, │ │
│ │ asgiref.typing.HTTPDisconnectEvent, │ │
│ │ asgiref.typing.WebSocketConnectEvent, │ │
│ │ asgiref.typing.WebSocketReceiveEvent, │ │
│ │ asgiref.typing.WebSocketDisconnectEvent, │ │
│ │ asgiref.typing.LifespanStartupEvent, │ │
│ │ asgiref.typing.LifespanShutdownEvent] │ │
│ │ ASGIScope = typing.Union[asgiref.typing.HTTPScope, │ │
│ │ asgiref.typing.WebSocketScope, │ │
│ │ asgiref.typing.LifespanScope] │ │
│ │ ASGISendCallable = typing.Callable[[typing.Union[asgiref.typing.HTTP… │ │
│ │ asgiref.typing.HTTPResponseBodyEvent, │ │
│ │ asgiref.typing.HTTPResponseTrailersEvent, │ │
│ │ asgiref.typing.HTTPServerPushEvent, │ │
│ │ asgiref.typing.HTTPDisconnectEvent, │ │
│ │ asgiref.typing.WebSocketAcceptEvent, │ │
│ │ asgiref.typing.WebSocketSendEvent, │ │
│ │ asgiref.typing.WebSocketResponseStartEvent, │ │
│ │ asgiref.typing.WebSocketResponseBodyEvent, │ │
│ │ asgiref.typing.WebSocketCloseEvent, │ │
│ │ asgiref.typing.LifespanStartupCompleteEvent, │ │
│ │ asgiref.typing.LifespanStartupFailedEvent, │ │
│ │ asgiref.typing.LifespanShutdownCompleteEvent, │ │
│ │ asgiref.typing.LifespanShutdownFailedEvent]], │ │
│ │ typing.Awaitable[NoneType]] │ │
│ │ ASGISendEvent = typing.Union[asgiref.typing.HTTPResponseStartEven… │ │
│ │ asgiref.typing.HTTPResponseBodyEvent, │ │
│ │ asgiref.typing.HTTPResponseTrailersEvent, │ │
│ │ asgiref.typing.HTTPServerPushEvent, │ │
│ │ asgiref.typing.HTTPDisconnectEvent, │ │
│ │ asgiref.typing.WebSocketAcceptEvent, │ │
│ │ asgiref.typing.WebSocketSendEvent, │ │
│ │ asgiref.typing.WebSocketResponseStartEvent, │ │
│ │ asgiref.typing.WebSocketResponseBodyEvent, │ │
│ │ asgiref.typing.WebSocketCloseEvent, │ │
│ │ asgiref.typing.LifespanStartupCompleteEvent, │ │
│ │ asgiref.typing.LifespanStartupFailedEvent, │ │
│ │ asgiref.typing.LifespanShutdownCompleteEvent, │ │
│ │ asgiref.typing.LifespanShutdownFailedEvent] │ │
│ │ AsyncGenerator = typing.AsyncGenerator │ │
│ │ AUDIT_LOG_LEVEL = 'NONE' │ │
│ │ Dict = typing.Dict │ │
│ │ logger = <loguru.logger handlers=[(id=0, level=10, │ │
│ │ sink=)]> │ │
│ │ MAX_BODY_LOG_SIZE = 2048 │ │
│ │ MutableMapping = typing.MutableMapping │ │
│ │ Optional = typing.Optional │ │
│ │ re = <module 're' from │ │
│ │ '/usr/local/lib/python3.12/re/__init__.py'> │ │
│ │ TYPE_CHECKING = False │ │
│ │ uuid = <module 'uuid' from │ │
│ │ '/usr/local/lib/python3.12/uuid.py'> │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/utils/auth.py:18 in │
│ │
│ │
│ 15 │
│ 16 from opentelemetry import trace │
│ 17 │
│ ❱ 18 from open_webui.models.users import Users │
│ 19 │
│ 20 from open_webui.constants import ERROR_MESSAGES │
│ 21 from open_webui.env import ( │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ base64 = <module 'base64' from '/usr/local/lib/python3.12/base64.py'> │ │
│ │ Dict = typing.Dict │ │
│ │ hashlib = <module 'hashlib' from │ │
│ │ '/usr/local/lib/python3.12/hashlib.py'> │ │
│ │ hmac = <module 'hmac' from '/usr/local/lib/python3.12/hmac.py'> │ │
│ │ jwt = <module 'jwt' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/jwt/__init__.py'> │ │
│ │ List = typing.List │ │
│ │ logging = <module 'logging' from │ │
│ │ '/usr/local/lib/python3.12/logging/__init__.py'> │ │
│ │ Optional = typing.Optional │ │
│ │ os = <module 'os' (frozen)> │ │
│ │ pytz = <module 'pytz' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/pytz/__init__.py'> │ │
│ │ requests = <module 'requests' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/requests/init.p… │ │
│ │ trace = <module 'opentelemetry.trace' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/opentelemetry/trace… │ │
│ │ Union = typing.Union │ │
│ │ UTC = │ │
│ │ uuid = <module 'uuid' from '/usr/local/lib/python3.12/uuid.py'> │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/models/users.py:4 in │
│ │
│ │
│ 1 import time │
│ 2 from typing import Optional │
│ 3 │
│ ❱ 4 from open_webui.internal.db import Base, JSONField, get_db │
│ 5 │
│ 6 │
│ 7 from open_webui.models.chats import Chats │
│ │
│ ╭─────────────── locals ────────────────╮ │
│ │ Optional = typing.Optional │ │
│ │ time = <module 'time' (built-in)> │ │
│ ╰───────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/internal/db.py:75 in │
│ │
│ │
│ 72 │ │ assert db.is_closed(), "Database connection is still open." │
│ 73 │
│ 74 │
│ ❱ 75 handle_peewee_migration(DATABASE_URL) │
│ 76 │
│ 77 │
│ 78 SQLALCHEMY_DATABASE_URL = DATABASE_URL │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ _T = ~_T │ │
│ │ DATABASE_POOL_MAX_OVERFLOW = 0 │ │
│ │ DATABASE_POOL_RECYCLE = 3600 │ │
│ │ DATABASE_POOL_SIZE = 0 │ │
│ │ DATABASE_POOL_TIMEOUT = 30 │ │
│ │ DATABASE_SCHEMA = None │ │
│ │ DATABASE_URL = 'postgresql+psycopg2://openwebui:openwebui… │ │
│ │ json = <module 'json' from │ │
│ │ '/usr/local/lib/python3.12/json/init.p… │ │
│ │ log = <Logger open_webui.internal.db (INFO)> │ │
│ │ logging = <module 'logging' from │ │
│ │ '/usr/local/lib/python3.12/logging/_init… │ │
│ │ OPEN_WEBUI_DIR = PosixPath('/usr/local/lib/python3.12/site-… │ │
│ │ Optional = typing.Optional │ │
│ │ Self = typing.Self │ │
│ │ SRC_LOG_LEVELS = { │ │
│ │ │ 'AUDIO': 'INFO', │ │
│ │ │ 'COMFYUI': 'INFO', │ │
│ │ │ 'CONFIG': 'INFO', │ │
│ │ │ 'DB': 'INFO', │ │
│ │ │ 'IMAGES': 'INFO', │ │
│ │ │ 'MAIN': 'INFO', │ │
│ │ │ 'MODELS': 'INFO', │ │
│ │ │ 'OLLAMA': 'INFO', │ │
│ │ │ 'OPENAI': 'INFO', │ │
│ │ │ 'RAG': 'INFO', │ │
│ │ │ ... +3 │ │
│ │ } │ │
│ │ types = <module 'sqlalchemy.types' from │ │
│ │ '/usr/local/lib/python3.12/site-packages/s… │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
│ │
│ /usr/local/lib/python3.12/site-packages/open_webui/internal/db.py:68 in │
│ handle_peewee_migration │
│ │
│ 65 │ │ raise │
│ 66 │ finally: │
│ 67 │ │ # Properly closing the database connection │
│ ❱ 68 │ │ if db and not db.is_closed(): │
│ 69 │ │ │ db.close() │
│ 70 │ │ │
│ 71 │ │ # Assert if db connection has been closed │
│ │
│ ╭───────────────────────────────── locals ─────────────────────────────────╮ │
│ │ DATABASE_URL = 'postgresql+psycopg2://openwebui:openwebui@postgres:5432… │ │
│ ╰──────────────────────────────────────────────────────────────────────────╯ │
╰──────────────────────────────────────────────────────────────────────────────╯
UnboundLocalError: cannot access local variable 'db' where it is not associated
with a value
Loading WEBUI_SECRET_KEY from file, not provided as an environment variable.
Loading WEBUI_SECRET_KEY from /app/.webui_secret_key

Additional Information

can pip installed open-webui use postgresql backend when installed in docker image?

Originally created by @erenirmak on GitHub (May 20, 2025). Original GitHub issue: https://github.com/open-webui/open-webui/issues/14081 ### Check Existing Issues - [x] I have searched the existing issues and discussions. - [x] I am using the latest version of Open WebUI. ### Installation Method Pip Install ### Open WebUI Version 0.6.10 ### Ollama Version (if applicable) _No response_ ### Operating System Windows ### Browser (if applicable) _No response_ ### Confirmation - [x] I have read and followed all instructions in `README.md`. - [x] I am using the latest version of **both** Open WebUI and Ollama. - [x] I have included the browser console logs. - [x] I have included the Docker container logs. - [x] I have listed steps to reproduce the bug in detail. ### Expected Behavior I defined DATABASE_URL env to be able to postgresql as a backend. tables should be created in the database. ### Actual Behavior It says: Failed to initialize the database connection: Unrecognized or unsupported scheme: "postgresql+psycopg2". ### Steps to Reproduce 1. created dockerfile. using python:3.12.10 image. Installing some libraries besides open-webui. Complete Dockerfile: ``` FROM python:3.12.10 WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt ENV DATA_DIR=/app/data ENV ENABLE_OLLAMA_API=True ENV OLLAMA_BASE_URL=http://10.0.0.30:11434 ENV PHOENIX_COLLECTOR_ENDPOINT=http://10.0.0.1:6006 ENV PHOENIX_PROJECT_NAME=openwebui EXPOSE 8080 CMD ["open-webui", "serve"] ``` 2. created docker-compose.yml file. setting some environment variables, as well as other services. Complete docker-compose.yml file: ``` services: open-webui: build: . ports: - "8080:8080" container_name: open-webui depends_on: - postgres - tika - playwright environment: - DATABASE_URL=postgresql+psycopg2://openwebui:openwebui@postgres/postgres - CONTENT_EXTRACTION_ENGINE=tika - TIKA_SERVER_URL=http://tika:9998/ - PGVECTOR_DB_URL=postgresql+psycopg2://openwebui:openwebui@postgres/openwebui - PDF_EXTRACT_IMAGES=true - ENABLE_WEB_SEARCH=true - WEB_SEARCH_ENGINE=duckduckgo - WEB_LOADER_ENGINE=playwright - PLAYWRIGHT_WS_URL=ws://playwright:3000 volumes: - ./data:/app/data restart: unless-stopped tika: image: apache/tika:latest-full container_name: tika ports: - "9998:9998" restart: unless-stopped postgres: image: pgvector/pgvector:0.8.0-pg16 container_name: postgres environment: POSTGRES_USER: openwebui POSTGRES_PASSWORD: openwebui POSTGRES_DB: openwebui ports: - "5432:5432" volumes: - pgdata:/var/lib/postgresql/data restart: unless-stopped playwright: image: mcr.microsoft.com/playwright:v1.49.1-noble container_name: playwright command: npx -y playwright@1.49.1 run-server --port 3000 --host 0.0.0.0 volumes: pgdata: driver: local ``` 3. running "docker compose up -d" 4. checking logs with "docker logs open-webui" it says: "unrecognized schema" error, cannot connect to postgresql database. P.S. actual values are different. changed them to something generic for convenience. ### Logs & Screenshots user@machine OpenWebUI>docker logs open-webui Loading WEBUI_SECRET_KEY from file, not provided as an environment variable. Generating a new secret key and saving it to /app/.webui_secret_key Loading WEBUI_SECRET_KEY from /app/.webui_secret_key Failed to initialize the database connection: Unrecognized or unsupported scheme: "postgresql+psycopg2". /usr/local/lib/python3.12/site-packages/open_webui /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12 ╭───────────────────── Traceback (most recent call last) ──────────────────────╮ │ /usr/local/lib/python3.12/site-packages/open_webui/internal/db.py:57 in │ │ handle_peewee_migration │ │ │ │ 54 │ # db = None │ │ 55 │ try: │ │ 56 │ │ # Replace the postgresql:// with postgres:// to handle the pee │ │ ❱ 57 │ │ db = register_connection(DATABASE_URL.replace("postgresql://", │ │ 58 │ │ migrate_dir = OPEN_WEBUI_DIR / "internal" / "migrations" │ │ 59 │ │ router = Router(db, logger=log, migrate_dir=migrate_dir) │ │ 60 │ │ router.run() │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ DATABASE_URL = 'postgresql+psycopg2://openwebui:openwebui@postgres:5432… │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/internal/wrappers.py:46 │ │ in register_connection │ │ │ │ 43 │ │ 44 │ │ 45 def register_connection(db_url): │ │ ❱ 46 │ db = connect(db_url, unquote_password=True) │ │ 47 │ if isinstance(db, PostgresqlDatabase): │ │ 48 │ │ # Enable autoconnect for SQLite databases, managed by Peewee │ │ 49 │ │ db.autoconnect = True │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ db_url = 'postgresql+psycopg2://openwebui:openwebui@postgres:5432/postg… │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/playhouse/db_url.py:103 in connect │ │ │ │ 100 │ │ │ raise RuntimeError('Attempted to use "%s" but a required l │ │ 101 │ │ │ │ │ │ │ 'could not be imported.' % parsed.schem │ │ 102 │ │ else: │ │ ❱ 103 │ │ │ raise RuntimeError('Unrecognized or unsupported scheme: "% │ │ 104 │ │ │ │ │ │ │ parsed.scheme) │ │ 105 │ │ │ 106 │ return database_class(**connect_kwargs) │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ connect_kwargs = { │ │ │ │ │ 'database': 'postgres', │ │ │ │ │ 'user': 'openwebui', │ │ │ │ │ 'password': 'openwebui', │ │ │ │ │ 'host': 'postgres', │ │ │ │ │ 'port': 5432 │ │ │ │ } │ │ │ │ connect_params = {} │ │ │ │ database_class = None │ │ │ │ parsed = ParseResult( │ │ │ │ │ scheme='postgresql+psycopg2', │ │ │ │ │ netloc='openwebui:openwebui@postgres:5432', │ │ │ │ │ path='/postgres', │ │ │ │ │ params='', │ │ │ │ │ query='', │ │ │ │ │ fragment='' │ │ │ │ ) │ │ │ │ unquote_password = True │ │ │ │ url = 'postgresql+psycopg2://openwebui:openwebui@postgres:… │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ ╰──────────────────────────────────────────────────────────────────────────────╯ RuntimeError: Unrecognized or unsupported scheme: "postgresql+psycopg2". During handling of the above exception, another exception occurred: ╭───────────────────── Traceback (most recent call last) ──────────────────────╮ │ /usr/local/lib/python3.12/site-packages/open_webui/__init__.py:75 in serve │ │ │ │ 72 │ │ │ os.environ["USE_CUDA_DOCKER"] = "false" │ │ 73 │ │ │ os.environ["LD_LIBRARY_PATH"] = ":".join(LD_LIBRARY_PATH) │ │ 74 │ │ │ ❱ 75 │ import open_webui.main # we need set environment variables before │ │ 76 │ from open_webui.env import UVICORN_WORKERS # Import the workers s │ │ 77 │ │ │ 78 │ uvicorn.run( │ │ │ │ ╭───── locals ─────╮ │ │ │ host = '0.0.0.0' │ │ │ │ port = 8080 │ │ │ ╰──────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/main.py:50 in <module> │ │ │ │ 47 │ │ 48 │ │ 49 from open_webui.utils import logger │ │ ❱ 50 from open_webui.utils.audit import AuditLevel, AuditLoggingMiddleware │ │ 51 from open_webui.utils.logger import start_logger │ │ 52 from open_webui.socket.main import ( │ │ 53 │ app as socket_app, │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ aiohttp = <module 'aiohttp' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/aiohttp/__init_… │ │ │ │ anyio = <module 'anyio' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/anyio/__init__.… │ │ │ │ applications = <module 'fastapi.applications' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/fastapi/applica… │ │ │ │ asyncio = <module 'asyncio' from │ │ │ │ '/usr/local/lib/python3.12/asyncio/__init__.py'> │ │ │ │ inspect = <module 'inspect' from │ │ │ │ '/usr/local/lib/python3.12/inspect.py'> │ │ │ │ json = <module 'json' from │ │ │ │ '/usr/local/lib/python3.12/json/__init__.py'> │ │ │ │ logger = <module 'open_webui.utils.logger' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/open_webui/util… │ │ │ │ logging = <module 'logging' from │ │ │ │ '/usr/local/lib/python3.12/logging/__init__.py'> │ │ │ │ mimetypes = <module 'mimetypes' from │ │ │ │ '/usr/local/lib/python3.12/mimetypes.py'> │ │ │ │ Optional = typing.Optional │ │ │ │ os = <module 'os' (frozen)> │ │ │ │ random = <module 'random' from │ │ │ │ '/usr/local/lib/python3.12/random.py'> │ │ │ │ requests = <module 'requests' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/requests/__init… │ │ │ │ shutil = <module 'shutil' from │ │ │ │ '/usr/local/lib/python3.12/shutil.py'> │ │ │ │ status = <module 'starlette.status' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/starlette/statu… │ │ │ │ sys = <module 'sys' (built-in)> │ │ │ │ time = <module 'time' (built-in)> │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/utils/audit.py:28 in │ │ <module> │ │ │ │ 25 from starlette.requests import Request │ │ 26 │ │ 27 from open_webui.env import AUDIT_LOG_LEVEL, MAX_BODY_LOG_SIZE │ │ ❱ 28 from open_webui.utils.auth import get_current_user, get_http_authoriza │ │ 29 from open_webui.models.users import UserModel │ │ 30 │ │ 31 │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ ASGI3Application = typing.Callable[[typing.Union[asgiref.typing.HTTP… │ │ │ │ asgiref.typing.WebSocketScope, │ │ │ │ asgiref.typing.LifespanScope], typing.Callable[[], │ │ │ │ typing.Awaitable[typing.Union[asgiref.typing.HTTP… │ │ │ │ asgiref.typing.HTTPDisconnectEvent, │ │ │ │ asgiref.typing.WebSocketConnectEvent, │ │ │ │ asgiref.typing.WebSocketReceiveEvent, │ │ │ │ asgiref.typing.WebSocketDisconnectEvent, │ │ │ │ asgiref.typing.LifespanStartupEvent, │ │ │ │ asgiref.typing.LifespanShutdownEvent]]], │ │ │ │ typing.Callable[[typing.Union[asgiref.typing.HTTP… │ │ │ │ asgiref.typing.HTTPResponseBodyEvent, │ │ │ │ asgiref.typing.HTTPResponseTrailersEvent, │ │ │ │ asgiref.typing.HTTPServerPushEvent, │ │ │ │ asgiref.typing.HTTPDisconnectEvent, │ │ │ │ asgiref.typing.WebSocketAcceptEvent, │ │ │ │ asgiref.typing.WebSocketSendEvent, │ │ │ │ asgiref.typing.WebSocketResponseStartEvent, │ │ │ │ asgiref.typing.WebSocketResponseBodyEvent, │ │ │ │ asgiref.typing.WebSocketCloseEvent, │ │ │ │ asgiref.typing.LifespanStartupCompleteEvent, │ │ │ │ asgiref.typing.LifespanStartupFailedEvent, │ │ │ │ asgiref.typing.LifespanShutdownCompleteEvent, │ │ │ │ asgiref.typing.LifespanShutdownFailedEvent]], │ │ │ │ typing.Awaitable[NoneType]]], │ │ │ │ typing.Awaitable[NoneType]] │ │ │ │ ASGIReceiveCallable = typing.Callable[[], │ │ │ │ typing.Awaitable[typing.Union[asgiref.typing.HTTP… │ │ │ │ asgiref.typing.HTTPDisconnectEvent, │ │ │ │ asgiref.typing.WebSocketConnectEvent, │ │ │ │ asgiref.typing.WebSocketReceiveEvent, │ │ │ │ asgiref.typing.WebSocketDisconnectEvent, │ │ │ │ asgiref.typing.LifespanStartupEvent, │ │ │ │ asgiref.typing.LifespanShutdownEvent]]] │ │ │ │ ASGIReceiveEvent = typing.Union[asgiref.typing.HTTPRequestEvent, │ │ │ │ asgiref.typing.HTTPDisconnectEvent, │ │ │ │ asgiref.typing.WebSocketConnectEvent, │ │ │ │ asgiref.typing.WebSocketReceiveEvent, │ │ │ │ asgiref.typing.WebSocketDisconnectEvent, │ │ │ │ asgiref.typing.LifespanStartupEvent, │ │ │ │ asgiref.typing.LifespanShutdownEvent] │ │ │ │ ASGIScope = typing.Union[asgiref.typing.HTTPScope, │ │ │ │ asgiref.typing.WebSocketScope, │ │ │ │ asgiref.typing.LifespanScope] │ │ │ │ ASGISendCallable = typing.Callable[[typing.Union[asgiref.typing.HTTP… │ │ │ │ asgiref.typing.HTTPResponseBodyEvent, │ │ │ │ asgiref.typing.HTTPResponseTrailersEvent, │ │ │ │ asgiref.typing.HTTPServerPushEvent, │ │ │ │ asgiref.typing.HTTPDisconnectEvent, │ │ │ │ asgiref.typing.WebSocketAcceptEvent, │ │ │ │ asgiref.typing.WebSocketSendEvent, │ │ │ │ asgiref.typing.WebSocketResponseStartEvent, │ │ │ │ asgiref.typing.WebSocketResponseBodyEvent, │ │ │ │ asgiref.typing.WebSocketCloseEvent, │ │ │ │ asgiref.typing.LifespanStartupCompleteEvent, │ │ │ │ asgiref.typing.LifespanStartupFailedEvent, │ │ │ │ asgiref.typing.LifespanShutdownCompleteEvent, │ │ │ │ asgiref.typing.LifespanShutdownFailedEvent]], │ │ │ │ typing.Awaitable[NoneType]] │ │ │ │ ASGISendEvent = typing.Union[asgiref.typing.HTTPResponseStartEven… │ │ │ │ asgiref.typing.HTTPResponseBodyEvent, │ │ │ │ asgiref.typing.HTTPResponseTrailersEvent, │ │ │ │ asgiref.typing.HTTPServerPushEvent, │ │ │ │ asgiref.typing.HTTPDisconnectEvent, │ │ │ │ asgiref.typing.WebSocketAcceptEvent, │ │ │ │ asgiref.typing.WebSocketSendEvent, │ │ │ │ asgiref.typing.WebSocketResponseStartEvent, │ │ │ │ asgiref.typing.WebSocketResponseBodyEvent, │ │ │ │ asgiref.typing.WebSocketCloseEvent, │ │ │ │ asgiref.typing.LifespanStartupCompleteEvent, │ │ │ │ asgiref.typing.LifespanStartupFailedEvent, │ │ │ │ asgiref.typing.LifespanShutdownCompleteEvent, │ │ │ │ asgiref.typing.LifespanShutdownFailedEvent] │ │ │ │ AsyncGenerator = typing.AsyncGenerator │ │ │ │ AUDIT_LOG_LEVEL = 'NONE' │ │ │ │ Dict = typing.Dict │ │ │ │ logger = <loguru.logger handlers=[(id=0, level=10, │ │ │ │ sink=<stderr>)]> │ │ │ │ MAX_BODY_LOG_SIZE = 2048 │ │ │ │ MutableMapping = typing.MutableMapping │ │ │ │ Optional = typing.Optional │ │ │ │ re = <module 're' from │ │ │ │ '/usr/local/lib/python3.12/re/__init__.py'> │ │ │ │ TYPE_CHECKING = False │ │ │ │ uuid = <module 'uuid' from │ │ │ │ '/usr/local/lib/python3.12/uuid.py'> │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/utils/auth.py:18 in │ │ <module> │ │ │ │ 15 │ │ 16 from opentelemetry import trace │ │ 17 │ │ ❱ 18 from open_webui.models.users import Users │ │ 19 │ │ 20 from open_webui.constants import ERROR_MESSAGES │ │ 21 from open_webui.env import ( │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ base64 = <module 'base64' from '/usr/local/lib/python3.12/base64.py'> │ │ │ │ Dict = typing.Dict │ │ │ │ hashlib = <module 'hashlib' from │ │ │ │ '/usr/local/lib/python3.12/hashlib.py'> │ │ │ │ hmac = <module 'hmac' from '/usr/local/lib/python3.12/hmac.py'> │ │ │ │ jwt = <module 'jwt' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/jwt/__init__.py'> │ │ │ │ List = typing.List │ │ │ │ logging = <module 'logging' from │ │ │ │ '/usr/local/lib/python3.12/logging/__init__.py'> │ │ │ │ Optional = typing.Optional │ │ │ │ os = <module 'os' (frozen)> │ │ │ │ pytz = <module 'pytz' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/pytz/__init__.py'> │ │ │ │ requests = <module 'requests' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/requests/__init__.p… │ │ │ │ trace = <module 'opentelemetry.trace' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/opentelemetry/trace… │ │ │ │ Union = typing.Union │ │ │ │ UTC = <UTC> │ │ │ │ uuid = <module 'uuid' from '/usr/local/lib/python3.12/uuid.py'> │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/models/users.py:4 in │ │ <module> │ │ │ │ 1 import time │ │ 2 from typing import Optional │ │ 3 │ │ ❱ 4 from open_webui.internal.db import Base, JSONField, get_db │ │ 5 │ │ 6 │ │ 7 from open_webui.models.chats import Chats │ │ │ │ ╭─────────────── locals ────────────────╮ │ │ │ Optional = typing.Optional │ │ │ │ time = <module 'time' (built-in)> │ │ │ ╰───────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/internal/db.py:75 in │ │ <module> │ │ │ │ 72 │ │ assert db.is_closed(), "Database connection is still open." │ │ 73 │ │ 74 │ │ ❱ 75 handle_peewee_migration(DATABASE_URL) │ │ 76 │ │ 77 │ │ 78 SQLALCHEMY_DATABASE_URL = DATABASE_URL │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ _T = ~_T │ │ │ │ DATABASE_POOL_MAX_OVERFLOW = 0 │ │ │ │ DATABASE_POOL_RECYCLE = 3600 │ │ │ │ DATABASE_POOL_SIZE = 0 │ │ │ │ DATABASE_POOL_TIMEOUT = 30 │ │ │ │ DATABASE_SCHEMA = None │ │ │ │ DATABASE_URL = 'postgresql+psycopg2://openwebui:openwebui… │ │ │ │ json = <module 'json' from │ │ │ │ '/usr/local/lib/python3.12/json/__init__.p… │ │ │ │ log = <Logger open_webui.internal.db (INFO)> │ │ │ │ logging = <module 'logging' from │ │ │ │ '/usr/local/lib/python3.12/logging/__init_… │ │ │ │ OPEN_WEBUI_DIR = PosixPath('/usr/local/lib/python3.12/site-… │ │ │ │ Optional = typing.Optional │ │ │ │ Self = typing.Self │ │ │ │ SRC_LOG_LEVELS = { │ │ │ │ │ 'AUDIO': 'INFO', │ │ │ │ │ 'COMFYUI': 'INFO', │ │ │ │ │ 'CONFIG': 'INFO', │ │ │ │ │ 'DB': 'INFO', │ │ │ │ │ 'IMAGES': 'INFO', │ │ │ │ │ 'MAIN': 'INFO', │ │ │ │ │ 'MODELS': 'INFO', │ │ │ │ │ 'OLLAMA': 'INFO', │ │ │ │ │ 'OPENAI': 'INFO', │ │ │ │ │ 'RAG': 'INFO', │ │ │ │ │ ... +3 │ │ │ │ } │ │ │ │ types = <module 'sqlalchemy.types' from │ │ │ │ '/usr/local/lib/python3.12/site-packages/s… │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ │ │ │ /usr/local/lib/python3.12/site-packages/open_webui/internal/db.py:68 in │ │ handle_peewee_migration │ │ │ │ 65 │ │ raise │ │ 66 │ finally: │ │ 67 │ │ # Properly closing the database connection │ │ ❱ 68 │ │ if db and not db.is_closed(): │ │ 69 │ │ │ db.close() │ │ 70 │ │ │ │ 71 │ │ # Assert if db connection has been closed │ │ │ │ ╭───────────────────────────────── locals ─────────────────────────────────╮ │ │ │ DATABASE_URL = 'postgresql+psycopg2://openwebui:openwebui@postgres:5432… │ │ │ ╰──────────────────────────────────────────────────────────────────────────╯ │ ╰──────────────────────────────────────────────────────────────────────────────╯ UnboundLocalError: cannot access local variable 'db' where it is not associated with a value Loading WEBUI_SECRET_KEY from file, not provided as an environment variable. Loading WEBUI_SECRET_KEY from /app/.webui_secret_key ### Additional Information can pip installed open-webui use postgresql backend when installed in docker image?
GiteaMirror added the bug label 2026-05-25 05:35:58 -05: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#136860