dani-garcia/vaultwarden · error
Error loading push devices
Error message
Error loading push devices
What it means
Panic from `.expect()` on the Diesel query in `Device::find_push_devices_by_user`, which loads a user's devices that have a non-null push_token. Any SQL failure (connection loss, schema drift, bad query) is treated as fatal and panics. Absence of push devices is NOT this error — that just yields an empty vec.
Solutions
- Ensure the `devices.push_token` column exists (run all pending migrations by restarting the server)
- Check database availability and connection-pool settings (DB_TIMEOUT, max connections)
- Fix the root Diesel error shown in the log before the panic (connectivity, permissions, missing table)
- If push notifications were recently enabled, verify schema matches the new version before deploying
Example fix
// before
.load::<Self>(conn).expect("Error loading push devices")
// after
.load::<Self>(conn).map_err(|e| err!(DbError, "Error loading push devices: {e}")) Defensive patterns
Strategy: try-catch
Validate before calling
// ensure the push_token column exists on old databases // SELECT push_token FROM devices LIMIT 1; (fails on pre-migration schema)
Try / catch
// Treat DB failure as service degradation: return empty push list or 503, not a crash let devices = find_push_devices().unwrap_or_default();
Prevention
- Apply schema migrations when enabling push notifications (push_token column)
- Test DB connectivity after enabling PUSH_ENABLED before traffic ramps
- Watch DB connection-limit metrics under load
- Keep backups of the devices table before upgrades
When it happens
Trigger: Querying push devices for a user during a DB outage; after a migration that altered `devices` (e.g. missing `push_token` column on an older DB); stale pooled connections after a database restart.
Common situations: Older database upgraded to a Vaultwarden version requiring the `push_token` column; MySQL/Postgres max_connections exhausted under load; read-replica lag or failover mid-request.
Understand the failure class
Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.
Related errors
- Error loading ciphers
- Error loading collections
- Error loading devices
- Error loading emergency_access
- Error loading users_collections
AI-assisted analysis of dani-garcia/vaultwarden@cc67d644f6 (2026-09-19).
Data as JSON: /api/errors/f2477b8ab8885c7b.
Report an issue: GitHub.
Appendix: source
Thrown at src/db/models/device.rs:247
pub async fn find_latest_active_by_user(user_uuid: &UserId, conn: &DbConn) -> Option<Self> {
conn.run(move |conn| {
devices::table
.filter(devices::user_uuid.eq(user_uuid))
.order(devices::updated_at.desc())
.first::<Self>(conn)
.ok()
})
.await
}
pub async fn find_push_devices_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec<Self> {
conn.run(move |conn| {
devices::table
.filter(devices::user_uuid.eq(user_uuid))
.filter(devices::push_token.is_not_null())
.load::<Self>(conn)
.expect("Error loading push devices")
})
.await
}
pub async fn check_user_has_push_device(user_uuid: &UserId, conn: &DbConn) -> bool {
conn.run(move |conn| {
devices::table
.filter(devices::user_uuid.eq(user_uuid))
.filter(devices::push_token.is_not_null())
.count()
.first::<i64>(conn)
.ok()
.unwrap_or(0)
!= 0
})
.await
}
View on GitHub (pinned to cc67d644f6)