theonedev/onedev · warning · ExplicitException

Unable to send verification email as this email address is a

Error message

Unable to send verification email as this email address is already verified

What it means

If the email address is already verified, resending a verification email is pointless and rejected with ExplicitException. OneDev checks emailAddress.isVerified() before dispatching another verification mail.

Source

Thrown at server-core/src/main/java/io/onedev/server/rest/resource/EmailAddressResource.java:126

		if (!getAuthUser().equals(owner)) 
			auditService.audit(null, "set email address \"" + emailAddress.getValue() + "\" as primary in account \"" + owner.getName() + "\" via RESTful API", null, null);
		
		return emailAddressId;
	}
	
	@Api(order=260, description="Resend verification email")
	@Path("/resend-verification-email")
	@POST
	public Long resendVerificationEmail(@NotNull Long emailAddressId) {
		var emailAddress = emailAddressService.load(emailAddressId);
		if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser()))
			throw new UnauthorizedException();

		if (settingService.getMailConnector() == null)
			throw new ExplicitException("Unable to send verification email as mail service is not configured");
		if (emailAddress.isVerified())
			throw new ExplicitException("Unable to send verification email as this email address is already verified");
		
		emailAddressService.sendVerificationEmail(emailAddress);
		
		return emailAddressId;
	}
	
	@Api(order=300)
	@Path("/{emailAddressId}")
	@DELETE
	public Response deleteEmailAddress(@PathParam("emailAddressId") Long emailAddressId) {
		var emailAddress = emailAddressService.load(emailAddressId);
		if (!SecurityUtils.isAdministrator() && !emailAddress.getOwner().equals(getAuthUser())) 
			throw new UnauthorizedException();
		
		if (emailAddress.isPrimary() && emailAddress.getOwner().getPassword() == null) {
			throw new ExplicitException("Cannot delete primary email address of "
					+ "externally authenticated user");
		}

View on GitHub (pinned to d44925c47c)

Solutions

  1. Check emailAddress.isVerified() before calling and skip if already verified
  2. Treat this error as success in idempotent scripts (address is usable)
  3. Clear client state that still shows the address as unverified

Example fix

// before
resendVerificationEmail(id);
// after
if (!emailAddressService.load(id).isVerified()) resendVerificationEmail(id);
Defensive patterns

Strategy: validation

Validate before calling

if (emailAddress.isVerified()) skip resend;

Type guard

boolean needsVerification = !emailAddress.isVerified();

Try / catch

try { resendVerificationEmail(id); } catch (ExplicitException e) { /* already verified: treat as success */ }

Prevention

When it happens

Trigger: POST to /resend-verification-email for an address whose isVerified() is true — e.g. user already clicked the verification link.

Common situations: User double-clicks resend in the UI; queued/parallel resend requests after verification; scripts retrying an already-completed flow.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06). Data as JSON: /api/errors/8c95f1d2785c4198. Report an issue: GitHub.