dani-garcia/vaultwarden · error
Error loading devices
Error message
Error loading devices
What it means
Panic from an `.expect()` on a Diesel query in `Device::find_by_user`. The library considers any failure to load the `devices` rows for a user fatal and panics rather than returning an empty/failed result. It indicates a database-level failure (connectivity, schema mismatch), not simply that the user has no devices.
Solutions
- Verify DATABASE_URL connectivity and that the `devices` table exists with the expected columns
- Restart Vaultwarden to apply pending migrations and rebuild the connection pool
- Read the underlying Diesel error in the logs just above the panic and address it (connection, missing column, permissions)
- Check DB permissions for the configured user (SELECT on devices table)
Example fix
// before
.load::<Self>(conn).expect("Error loading devices")
// after
.load::<Self>(conn).map_err(|e| err!(DbError, "Error loading devices: {e}")) Defensive patterns
Strategy: try-catch
Validate before calling
// check the devices table is reachable first // SELECT 1 FROM devices LIMIT 1; — if this fails, skip device-dependent logic
Try / catch
// Catch or convert to a 503-style error instead of surfacing a raw panic
if let Err(e) = db_health_check() { return service_unavailable(e); } Prevention
- Run migrations before deploying new binary versions
- Keep connection pool settings (DB_TIMEOUT) tuned to your DB
- Restart the service after any database failover/restart
- Verify the DB user has SELECT on the devices table
When it happens
Trigger: Calling `Device::find_by_user` while the database is down or the connection was dropped, after a failed/partial migration that removed or renamed the `devices` table/columns, or with a corrupted database file.
Common situations: Upgrade applied without migrations completing; DB credentials changed in config; SQLite data.db moved or corrupted; MySQL/Postgres restarted and pool holds stale connections.
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 collections
- Error loading users_collections
- Error creating organization API Key
- Error loading ciphers
- Error loading emergency_access
AI-assisted analysis of dani-garcia/vaultwarden@cc67d644f6 (2026-09-19).
Data as JSON: /api/errors/c337cf9b037b8ce6.
Report an issue: GitHub.
Appendix: source
Thrown at src/db/models/device.rs:206
.first::<Self>(conn)
.ok()
})
.await
}
pub async fn find_with_auth_request_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec<DeviceWithAuthRequest> {
let devices = Self::find_by_user(user_uuid, conn).await;
let mut result = Vec::new();
for device in devices {
let auth_request = AuthRequest::find_by_user_and_requested_device(user_uuid, &device.uuid, conn).await;
result.push(DeviceWithAuthRequest::from(device, auth_request));
}
result
}
pub async fn find_by_user(user_uuid: &UserId, conn: &DbConn) -> Vec<Self> {
conn.run(move |conn| {
devices::table.filter(devices::user_uuid.eq(user_uuid)).load::<Self>(conn).expect("Error loading devices")
})
.await
}
pub async fn find_by_uuid(uuid: &DeviceId, conn: &DbConn) -> Option<Self> {
conn.run(move |conn| devices::table.filter(devices::uuid.eq(uuid)).first::<Self>(conn).ok()).await
}
pub async fn clear_push_token_by_uuid(uuid: &DeviceId, conn: &DbConn) -> EmptyResult {
conn.run(move |conn| {
diesel::update(devices::table)
.filter(devices::uuid.eq(uuid))
.set(devices::push_token.eq::<Option<String>>(None))
.execute(conn)
.map_res("Error removing push token")
})
.await
}View on GitHub (pinned to cc67d644f6)