toeverything/AFFiNE · warning · SameEmailProvided
same_email_provided
same_email_provided
Error message
You are trying to update your account email to the same as the old one.
What it means
Thrown by sendVerifyChangeEmail when getUserByEmail(email) resolves to the current user's own account (hasRegistered.id === user.id). The flow refuses to run a no-op email change to the address the user already owns.
Solutions
- Compare the entered email against currentUser.email client-side and block submission when equal
- Show the current email next to the input so the change target is obvious
- If hit in tests, update fixtures to use a genuinely different address
Example fix
// before
await client.request(sendVerifyChangeEmailMutation, { token, email, callbackUrl });
// after
if (email === me.email) {
setNotice('This is already your email address');
return;
}
await client.request(sendVerifyChangeEmailMutation, { token, email, callbackUrl }); Defensive patterns
Strategy: validation
Validate before calling
const normalized = email.trim().toLowerCase();
if (normalized === me.email) {
setNotice('This is already your email address');
} else {
await client.request(sendVerifyChangeEmailMutation, { token, email: normalized, callbackUrl });
} Prevention
- Compare trimmed/lowercased emails against the current one client-side
- Pre-fill nothing in the new-email field to avoid unchanged resubmission
- Use distinct fixture emails in tests
When it happens
Trigger: Calling sendVerifyChangeEmail with an email identical to the signed-in user's current email.
Common situations: User retypes their existing address out of habit; form pre-filled with the current email and submitted unchanged; copy/paste of the wrong row from a password manager.
Related errors
- email_token_not_found
- email_already_used
- action_forbidden
- copilot_doc_not_found
- description must be provided explicitly.
AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18).
Data as JSON: /api/errors/24de72fbbc2bfdb7.
Report an issue: GitHub.
Appendix: source
Thrown at packages/backend/server/src/core/auth/resolver.ts:278
const valid = await this.models.verificationToken.verify(
TokenType.ChangeEmail,
token,
{
credential: user.id,
}
);
if (!valid) {
throw new InvalidEmailToken();
}
const hasRegistered = await this.models.user.getUserByEmail(email);
if (hasRegistered) {
if (hasRegistered.id !== user.id) {
throw new EmailAlreadyUsed();
} else {
throw new SameEmailProvided();
}
}
const { token: verifyEmailToken, expiresAt } =
await this.models.verificationToken.createWithExpiresAt(
TokenType.VerifyEmail,
user.id
);
const url = this.url.safeLink(callbackUrl, {
token: verifyEmailToken,
email,
});
return await this.auth.sendVerifyChangeEmail(
email,
url,
this.mailMetadata(context, expiresAt)
);View on GitHub (pinned to b4c8548c09)