Found a few .expect() / .unwrap() calls that can crash the server or kill background jobs.
emergency_access.rs
emergency_request_timeout_job and emergency_notification_reminder_job: if any record had a missing field or a failed DB/mail call, the whole job thread panicked and the rest of the records were skipped silently. Now logs the error and continues with the next record.
GET /emergency-access/<id>: panicked when the grantee no longer exists. Returns a normal error now.
POST /emergency-access/invite: panicked when the email field was empty. Returns a normal error now.
is_valid_request: cleaned up is_some() && unwrap() == x to as_ref() == Some(x).
🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.
## 📋 Pull Request Information
**Original PR:** https://github.com/dani-garcia/vaultwarden/pull/7130
**Author:** [@nghiphaam](https://github.com/nghiphaam)
**Created:** 4/25/2026
**Status:** ❌ Closed
**Base:** `main` ← **Head:** `fix/avoid-panic-emergency-access-attachments`
---
### 📝 Commits (1)
- [`6451643`](https://github.com/dani-garcia/vaultwarden/commit/645164382ec63340b29cdd3b91e0d651c6afeaba) fix: avoid panic in emergency access jobs and attachment save
### 📊 Changes
**2 files changed** (+92 additions, -47 deletions)
<details>
<summary>View changed files</summary>
📝 `src/api/core/ciphers.rs` (+7 -9)
📝 `src/api/core/emergency_access.rs` (+85 -38)
</details>
### 📄 Description
Found a few `.expect()` / `.unwrap()` calls that can crash the server or kill background jobs.
### emergency_access.rs
- [emergency_request_timeout_job](cci:1://file:///home/nghipham/Downloads/vaultwarden-main/src/api/core/emergency_access.rs:720:0-794:1) and [emergency_notification_reminder_job](cci:1://file:///home/nghipham/Downloads/vaultwarden-main/src/api/core/emergency_access.rs:796:0-876:1): if any record had a missing field or a failed DB/mail call, the whole job thread panicked and the rest of the records were skipped silently. Now logs the error and continues with the next record.
- `GET /emergency-access/<id>`: panicked when the grantee no longer exists. Returns a normal error now.
- `POST /emergency-access/invite`: panicked when the email field was empty. Returns a normal error now.
- [is_valid_request](cci:1://file:///home/nghipham/Downloads/vaultwarden-main/src/api/core/emergency_access.rs:703:0-711:1): cleaned up `is_some() && unwrap() == x` to `as_ref() == Some(x)`.
### ciphers.rs
- Three [attachment.save().expect("Error saving attachment")](cci:1://file:///home/nghipham/Downloads/vaultwarden-main/src/db/models/cipher.rs:435:4-467:5) replaced with `.map_res("...")?` so a DB failure returns an error to the client instead of crashing the request.
- Removed a redundant `is_none()` check, using `let-else` instead.
### Not touched
- `unwrap()` on `TimeDelta::try_*` constants in [auth.rs](cci:7://file:///home/nghipham/Downloads/vaultwarden-main/src/auth.rs:0:0-0:0) — safe, constants.
- `unwrap()` in [identity.rs](cci:7://file:///home/nghipham/Downloads/vaultwarden-main/src/api/identity.rs:0:0-0:0) after [_check_is_some()](cci:1://file:///home/nghipham/Downloads/vaultwarden-main/src/api/identity.rs:1110:0-1115:1) — already validated.
---
<sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
📋 Pull Request Information
Original PR: https://github.com/dani-garcia/vaultwarden/pull/7130
Author: @nghiphaam
Created: 4/25/2026
Status: ❌ Closed
Base:
main← Head:fix/avoid-panic-emergency-access-attachments📝 Commits (1)
6451643fix: avoid panic in emergency access jobs and attachment save📊 Changes
2 files changed (+92 additions, -47 deletions)
View changed files
📝
src/api/core/ciphers.rs(+7 -9)📝
src/api/core/emergency_access.rs(+85 -38)📄 Description
Found a few
.expect()/.unwrap()calls that can crash the server or kill background jobs.emergency_access.rs
GET /emergency-access/<id>: panicked when the grantee no longer exists. Returns a normal error now.POST /emergency-access/invite: panicked when the email field was empty. Returns a normal error now.is_some() && unwrap() == xtoas_ref() == Some(x).ciphers.rs
.map_res("...")?so a DB failure returns an error to the client instead of crashing the request.is_none()check, usinglet-elseinstead.Not touched
unwrap()onTimeDelta::try_*constants in auth.rs — safe, constants.unwrap()in identity.rs after _check_is_some() — already validated.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.