open-webui/open-webui · critical · ValueError
DATABASE_PASSWORD is required when using sqlite+sqlcipher://
Error message
DATABASE_PASSWORD is required when using sqlite+sqlcipher:// URLs
What it means
SQLCipher branch of the sync engine setup in backend/open_webui/internal/db.py: when SQLALCHEMY_DATABASE_URL starts with sqlite+sqlcipher://, the code must execute "PRAGMA key = '<DATABASE_PASSWORD>'" to decrypt the database file. An unset, empty, or whitespace-only DATABASE_PASSWORD raises ValueError immediately, since opening an encrypted DB without a key is meaningless.
Source
Thrown at backend/open_webui/internal/db.py:244
return url.replace('postgresql+psycopg2://', 'postgresql+psycopg://', 1)
if url.startswith('postgresql://'):
return url.replace('postgresql://', 'postgresql+psycopg://', 1)
if url.startswith('postgres://'):
return url.replace('postgres://', 'postgresql+psycopg://', 1)
# For other dialects, return as-is and let SQLAlchemy handle it
return url
# ============================================================
# SYNC ENGINE (used only for: startup migrations, config loading,
# Alembic, peewee migration, health checks)
# ============================================================
# Handle SQLCipher URLs
if SQLALCHEMY_DATABASE_URL.startswith('sqlite+sqlcipher://'):
database_password = os.environ.get('DATABASE_PASSWORD')
if not database_password or database_password.strip() == '':
raise ValueError('DATABASE_PASSWORD is required when using sqlite+sqlcipher:// URLs')
# Extract database path from SQLCipher URL
db_path = SQLALCHEMY_DATABASE_URL.replace('sqlite+sqlcipher://', '')
# Create a custom creator function that uses sqlcipher3
def create_sqlcipher_connection():
import sqlcipher3
conn = sqlcipher3.connect(db_path, check_same_thread=False)
conn.execute(f"PRAGMA key = '{database_password}'")
return conn
# The dummy "sqlite://" URL would cause SQLAlchemy to auto-select
# SingletonThreadPool, which non-deterministically closes in-use
# connections when thread count exceeds pool_size, leading to segfaults
# in the native sqlcipher3 C library. Use NullPool by default for safety,
# or QueuePool if DATABASE_POOL_SIZE is explicitly configured.
if isinstance(DATABASE_POOL_SIZE, int) and DATABASE_POOL_SIZE > 0:View on GitHub (pinned to 01f4282f1f)
Solutions
- Set DATABASE_PASSWORD to the SQLCipher key: a non-empty string, e.g. DATABASE_PASSWORD=$(openssl rand -hex 32) stored securely.
- Verify it reaches the process (docker exec <container> printenv DATABASE_PASSWORD) and is not just set in the shell that built the image.
- Keep the same key for the life of the database file — losing it loses the data.
Example fix
# before DATABASE_URL=sqlite+sqlcipher:///data/webui.db # DATABASE_PASSWORD unset # after DATABASE_URL=sqlite+sqlcipher:///data/webui.db DATABASE_PASSWORD=<strong-random-key>
Defensive patterns
Strategy: validation
Validate before calling
import os
if os.environ.get('DATABASE_URL', '').startswith('sqlite+sqlcipher://'):
pw = os.environ.get('DATABASE_PASSWORD', '')
assert pw and pw.strip(), 'DATABASE_PASSWORD must be a non-empty key for sqlcipher URLs' Try / catch
try:
import open_webui.internal.db # noqa
except ValueError as e:
raise SystemExit(f'Database init failed: {e}') # missing key is fatal, do not retry Prevention
- Store the SQLCipher key in a secret manager and inject it as DATABASE_PASSWORD.
- Back up the key with the database backup — it is required to open the file.
When it happens
Trigger: DATABASE_URL=sqlite+sqlcipher:///data/webui.db with DATABASE_PASSWORD unset, empty (DATABASE_PASSWORD="" in .env counts as empty), or containing only whitespace.
Common situations: .env file defines the variable but with no value; secret injection failing so os.environ lacks it; whitespace/newline artifacts in the value; user expecting a prompt instead of hard failure.
Related errors
- sqlite+sqlcipher:// URLs are not supported with async engine
- PGVECTOR_PGCRYPTO is enabled but PGVECTOR_PGCRYPTO_KEY is no
- Oracle23ai requires setting ORACLE_DB_USER, ORACLE_DB_PASSWO
- DATABASE_ENABLE_IAM_TOKEN_AUTH is only supported for Postgre
- DATABASE_ENABLE_IAM_TOKEN_AUTH requires a database host and
AI-assisted analysis of open-webui/open-webui@01f4282f1f (2026-08-14).
Data as JSON: /api/errors/703104f35934d980.
Report an issue: GitHub.