dani-garcia/vaultwarden · error
Error loading emergency_access
Error message
Error loading emergency_access
What it means
Panic from `.expect()` on the Diesel query in `EmergencyAccess::find_all_recoveries_initiated`, which loads all emergency_access rows in RecoveryInitiated status. Any SQL failure (connection loss, missing table/column, permissions) is fatal and panics instead of returning an empty vec or error.
Solutions
- Verify database connectivity and that the `emergency_access` table/status column exist (run pending migrations)
- Read the underlying Diesel error in the logs above the panic and fix that cause
- Check DB user permissions (SELECT on emergency_access) and disk space for SQLite
- Restart the server to reset the connection pool after a DB outage
Example fix
// before
.load::<Self>(conn).expect("Error loading emergency_access")
// after
.load::<Self>(conn).map_err(|e| err!(DbError, "Error loading emergency_access: {e}")) Defensive patterns
Strategy: try-catch
Validate before calling
// verify emergency_access table is queryable before running recovery jobs // SELECT 1 FROM emergency_access LIMIT 1;
Try / catch
// Wrap the scheduled recovery scan so a DB failure logs and retries instead of crashing
if let Err(e) = run_recovery_scan() { log_error(e); schedule_retry(); } Prevention
- Ensure migrations run before the periodic job executes
- Monitor DB availability for scheduled-job windows
- Keep SQLite files off full disks and out of backup-tool locks
- Alert on Diesel/DB errors in logs before they escalate to panics
When it happens
Trigger: The periodic emergency-access recovery job or an API call listing initiated recoveries runs while the DB is unreachable, after a failed migration on the `emergency_access` table, or with corrupt/locked SQLite data.
Common situations: Upgrades where the emergency_access schema wasn't migrated; database restarted under load leaving stale pool connections; disk-full or locked SQLite file on nightly cron jobs.
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 push devices
- Error loading users_collections
AI-assisted analysis of dani-garcia/vaultwarden@cc67d644f6 (2026-09-19).
Data as JSON: /api/errors/d559fc12a8ce5a45.
Report an issue: GitHub.
Appendix: source
Thrown at src/db/models/emergency_access.rs:263
conn: &DbConn,
) -> Option<Self> {
conn.run(move |conn| {
emergency_access::table
.filter(emergency_access::grantor_uuid.eq(grantor_uuid))
.filter(emergency_access::grantee_uuid.eq(grantee_uuid).or(emergency_access::email.eq(email)))
.first::<Self>(conn)
.ok()
})
.await
}
pub async fn find_all_recoveries_initiated(conn: &DbConn) -> Vec<Self> {
conn.run(move |conn| {
emergency_access::table
.filter(emergency_access::status.eq(EmergencyAccessStatus::RecoveryInitiated as i32))
.filter(emergency_access::recovery_initiated_at.is_not_null())
.load::<Self>(conn)
.expect("Error loading emergency_access")
})
.await
}
pub async fn find_by_uuid_and_grantor_uuid(
uuid: &EmergencyAccessId,
grantor_uuid: &UserId,
conn: &DbConn,
) -> Option<Self> {
conn.run(move |conn| {
emergency_access::table
.filter(emergency_access::uuid.eq(uuid))
.filter(emergency_access::grantor_uuid.eq(grantor_uuid))
.first::<Self>(conn)
.ok()
})
.await
}View on GitHub (pinned to cc67d644f6)