Skip to content

Reject unrecognised DATABASE_URL instead of silent SQLite fallback#7061

Open
mfw78 wants to merge 3 commits intodani-garcia:mainfrom
mfw78:fix/sqlite-fallback-panic
Open

Reject unrecognised DATABASE_URL instead of silent SQLite fallback#7061
mfw78 wants to merge 3 commits intodani-garcia:mainfrom
mfw78:fix/sqlite-fallback-panic

Conversation

@mfw78
Copy link
Copy Markdown

@mfw78 mfw78 commented Apr 7, 2026

Summary

When DATABASE_URL does not match mysql: or postgresql:, vaultwarden silently treats it as a SQLite file path. Any misconfiguration (typo, quoting issue, garbage value) quietly creates an empty SQLite database instead of erroring. In containerised environments this means data loss on restart, which has bitten me personally and others (#2835, #1910, #860).

The partial fix in #2873 catches some cases by checking the parent directory, but does not help when the path resolves within an existing directory.

The core issue is that SQLite selection is implicit. Database selection for a secrets manager should be explicit, not a fallback. An operator who misconfigures their database URL should get a clear error, not a silent downgrade to a different database engine entirely.

Changes

  • DbConnType::from_url now recognises an explicit sqlite: scheme. URLs without any recognised scheme are still accepted as bare-path SQLite for backwards compatibility, but only if the file already exists. Otherwise the process panics with a clear message.
  • Default DATABASE_URL changed to sqlite://{data_folder}/db.sqlite3 so new deployments use the explicit scheme.
  • backup_sqlite and validate_config updated to handle the sqlite:// prefix.
  • .env.template updated accordingly.

Test plan

  • Fresh deployment with default config creates database normally
  • Existing bare-path DATABASE_URL=data/db.sqlite3 (file exists) still works
  • Misconfigured URL (e.g. foobar) panics with a helpful message
  • SQLite backup works with sqlite:// prefix
  • MySQL and PostgreSQL URLs unaffected

Fixes #7062

@tessus
Copy link
Copy Markdown
Contributor

tessus commented Apr 7, 2026

May I ask why a panic and not a proper error message and clean exit with a specific error code?

@mfw78
Copy link
Copy Markdown
Author

mfw78 commented Apr 8, 2026

Good catch, and fair point. The panic was a bit short-sighted on my part; this issue had actually bitten me personally so I was perhaps a touch too eager to make it loud. I've since had a proper look through the codebase and can see the established convention is to use err!() which propagates up through from_config() and gets caught by create_db_pool() with a clean exit(1). That's clearly the right approach.

I've pushed a follow-up commit that swaps the panic! for err!() to bring it in line with how the rest of the config validation works.

@mfw78 mfw78 changed the title Panic on unrecognised DATABASE_URL instead of silent SQLite fallback Reject unrecognised DATABASE_URL instead of silent SQLite fallback Apr 8, 2026
Copy link
Copy Markdown
Collaborator

@BlackDex BlackDex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small text change. But i think that is all, the rest LGTM.

Comment thread src/db/mod.rs Outdated
@mfw78 mfw78 requested a review from BlackDex April 10, 2026 08:39
@mfw78 mfw78 force-pushed the fix/sqlite-fallback-panic branch from d095438 to a86865d Compare April 10, 2026 08:40
@mfw78 mfw78 force-pushed the fix/sqlite-fallback-panic branch from a86865d to 5da1d40 Compare April 15, 2026 20:48
mfw78 added 3 commits April 26, 2026 01:46
Previously, any DATABASE_URL that did not match the mysql: or postgresql:
prefix was silently treated as a SQLite file path. This caused data loss
in containerised environments when the URL was misconfigured (typos,
quoting issues), as vaultwarden would create an ephemeral SQLite database
that was wiped on restart.

Now, an explicit sqlite:// prefix is supported and used as the default.
Bare paths without a recognised scheme are still accepted for backwards
compatibility, but only if the database file already exists. If not, the
process panics with a clear error message.

Relates to dani-garcia#2835, dani-garcia#1910, dani-garcia#860.
Follow the established codebase convention where configuration
validation errors use err!() to propagate gracefully, rather than
panic!(). The error propagates through from_config() and is caught
by create_db_pool() which logs and calls exit(1).
Per review feedback, 'scheme' is the more accurate term for the
sqlite:// portion of the URL.
@mfw78 mfw78 force-pushed the fix/sqlite-fallback-panic branch from 5da1d40 to ac5d1f6 Compare April 26, 2026 01:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Misconfigured DATABASE_URL silently falls back to SQLite, risking data loss

3 participants