dani-garcia/vaultwarden · warning
Grantee email does not exists
Error message
Grantee email does not exists
What it means
POST /emergency-access/invite with mail enabled: the invite is stored via EmergencyAccess::new(grantor_uuid, grantee_user.email /* String */, ...), which stores Some(email); the later new_emergency_access.email.expect("Grantee email does not exists") is therefore a defensive branch that cannot fire on this code path. If a future refactor or a pre-existing row with NULL email made it fire, the invite request would panic while sending the notification mail.
Source
Thrown at src/api/core/emergency_access.rs:266
if EmergencyAccess::find_by_grantor_uuid_and_grantee_uuid_or_email(
&grantor_user.uuid,
&grantee_user.uuid,
&grantee_user.email,
&conn,
)
.await
.is_some()
{
err!(format!("Grantee user already invited: {}", &grantee_user.email))
}
let mut new_emergency_access =
EmergencyAccess::new(grantor_user.uuid, grantee_user.email, emergency_access_status, new_type, wait_time_days);
new_emergency_access.save(&conn).await?;
if CONFIG.mail_enabled() {
mail::send_emergency_access_invite(
&new_emergency_access.email.expect("Grantee email does not exists"),
grantee_user.uuid,
new_emergency_access.uuid,
&grantor_user.name,
&grantor_user.email,
)
.await?;
} else if !new_user {
// if mail is not enabled immediately accept the invitation for existing users
new_emergency_access.accept_invite(&grantee_user.uuid, &email, &conn).await?;
}
Ok(())
}
#[post("/emergency-access/<emer_id>/reinvite")]
async fn resend_invite(emer_id: EmergencyAccessId, headers: Headers, conn: DbConn) -> EmptyResult {
check_emergency_access_enabled()?;
View on GitHub (pinned to 0cefa4cca7)
Solutions
- No action needed for normal operation
- If auditing: verify no NULL emails with SELECT uuid FROM emergency_access WHERE email IS NULL
- Code hardening: replace .expect with a graceful error path
Example fix
// before
&new_emergency_access.email.expect("Grantee email does not exists"),
// after
match new_emergency_access.email.as_deref() {
Some(email) => email,
None => err!("Grantee email missing on emergency access invite"),
}, Defensive patterns
Strategy: validation
Validate before calling
-- Detect rows that would trip the branch (should return zero rows) SELECT uuid, email FROM emergency_access WHERE email IS NULL OR email = '';
Prevention
- Never NULL out emergency_access.email in manual edits
- Keep invite flows on the standard API
- Re-run the check query after restores or migrations
When it happens
Trigger: Not reachable through the current invite flow (email is always Some here). Would require rows with NULL email from manual edits, or EmergencyAccess::new changing to accept Option<String>.
Common situations: Surfaces in static analysis / panic audits rather than production logs; NULL-email rows could only come from direct DB tampering or migration glitches.
Related errors
- Error on sending email
- Failed to parse overrides
- Grantee user should exist but does not!
- Unable to update emergency access status
- Grantor user not found
AI-assisted analysis of dani-garcia/vaultwarden@0cefa4cca7 (2026-08-16).
Data as JSON: /api/errors/bade0ef62830eb0c.
Report an issue: GitHub.