theonedev/onedev · error · ExplicitException

At least one receiver address should be specified

Error message

At least one receiver address should be specified

What it means

DefaultMailService.sendMail refuses to send an email when the to, cc, and bcc address lists are all empty, throwing an ExplicitException because JavaMail requires at least one recipient for a message.

Source

Thrown at server-core/src/main/java/io/onedev/server/mail/DefaultMailService.java:373

			if (references != null) {
				String firstReference = StringUtils.substringBefore(references, " ");
				Map<String, String> headers = CollectionUtils.newHashMap(
						"References", references, 
						"In-Reply-To", firstReference, 
						"Thread-Index", getThreadIndex(firstReference));
				for (Map.Entry<String, String> entry: headers.entrySet()) {
					message.addHeader(entry.getKey(), createFoldedHeaderValue(entry.getKey(), entry.getValue()));
				}
			}
			
			if (senderName == null || senderName.equalsIgnoreCase("onedev")) 
				senderName = getQuoteMark();
			else 
				senderName += " " + getQuoteMark();
			message.setFrom(createInetAddress(senderAddress, senderName));
			
			if (toList.isEmpty() && ccList.isEmpty() && bccList.isEmpty())
				throw new ExplicitException("At least one receiver address should be specified");
			
			message.setRecipients(RecipientType.TO, 
					toList.stream().map(it->createInetAddress(it, null)).toArray(InternetAddress[]::new));
			message.setRecipients(RecipientType.CC, 
					ccList.stream().map(it->createInetAddress(it, null)).toArray(InternetAddress[]::new));
			message.setRecipients(RecipientType.BCC, 
					bccList.stream().map(it->createInetAddress(it, null)).toArray(InternetAddress[]::new));
			if (replyAddress != null)
				message.setReplyTo(new InternetAddress[]{createInetAddress(replyAddress, null)});

			message.setSubject(subject);
			message.setContent(bodyPart);

			logger.debug("Sending email (subject: {}, to: {}, cc: {}, bcc: {})... ", subject, toList, ccList, bccList);

			try {
				submitToSendExecutor(smtpSetting.getConcurrency(), () -> {
					try {

View on GitHub (pinned to d44925c47c)

Solutions

  1. Guard the call site: skip sending when all recipient lists are empty instead of calling sendMail.
  2. Fix the recipient-computation logic so at least one valid address is produced.
  3. Add a default/agent address (e.g. admin) as fallback recipient.

Example fix

// before
mailService.sendMail(to, cc, bcc, subject, htmlBody, textBody, null, null, null);
// after
if (!to.isEmpty() || !cc.isEmpty() || !bcc.isEmpty())
    mailService.sendMail(to, cc, bcc, subject, htmlBody, textBody, null, null, null);
Defensive patterns

Strategy: validation

Validate before calling

if (to.isEmpty() && cc.isEmpty() && bcc.isEmpty()) return; // skip send

Type guard

boolean hasRecipient(List<String> to, List<String> cc, List<String> bcc) { return !to.isEmpty() || !cc.isEmpty() || !bcc.isEmpty(); }

Try / catch

try { mailService.sendMail(to, cc, bcc, ...); } catch (ExplicitException e) { log.warn("Skipping mail with no recipients"); }

Prevention

When it happens

Trigger: Invoking sendMail (or a caller like sendMailAsync) with empty lists for to, cc, and bcc.

Common situations: Notification logic computing recipients dynamically (e.g. watchers, subscribers) that ends up with zero recipients after filtering; mail template/config producing no addresses.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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