halo-dev/halo · warning · IllegalArgumentException

Email must not be blank

Error message

Email must not be blank

What it means

Thrown as IllegalArgumentException by DefaultSubscriberEmailResolver.ofEmail when the supplied email is null, empty, or whitespace-only. ofEmail builds an anonymous subscriber whose name encodes the email, so a blank email cannot produce a valid subscriber identity.

Source

Thrown at application/src/main/java/run/halo/app/notification/DefaultSubscriberEmailResolver.java:40

@RequiredArgsConstructor
public class DefaultSubscriberEmailResolver implements SubscriberEmailResolver {
    private final ReactiveExtensionClient client;

    @Override
    public Mono<String> resolve(Subscription.Subscriber subscriber) {
        var identity = UserIdentity.of(subscriber.getName());
        if (identity.isAnonymous()) {
            return Mono.fromSupplier(() -> getEmail(subscriber));
        }
        return client.fetch(User.class, subscriber.getName())
                .filter(user -> user.getSpec().isEmailVerified())
                .mapNotNull(user -> user.getSpec().getEmail());
    }

    @Override
    public Subscription.Subscriber ofEmail(String email) {
        if (StringUtils.isBlank(email)) {
            throw new IllegalArgumentException("Email must not be blank");
        }
        var subscriber = new Subscription.Subscriber();
        subscriber.setName(UserIdentity.anonymousWithEmail(email).name());
        return subscriber;
    }

    String getEmail(Subscription.Subscriber subscriber) {
        var identity = UserIdentity.of(subscriber.getName());
        if (!identity.isAnonymous()) {
            throw new IllegalStateException("The subscriber is not an anonymous subscriber");
        }
        return identity.getEmail()
                .filter(StringUtils::isNotBlank)
                .orElseThrow(() -> new IllegalStateException("The subscriber does not have an email"));
    }
}

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Validate the email is non-blank and well-formed before calling ofEmail.
  2. Return a 400 to the client when the email field is missing.
  3. Default to a required-field check in the form/controller.
  4. Trim and reject empty strings upstream.

Example fix

// before
var sub = resolver.ofEmail(req.getEmail()); // email null

// after
if (!StringUtils.hasText(req.getEmail()) || !req.getEmail().contains("@")) {
    return Mono.error(new ServerWebInputException("Valid email is required"));
}
var sub = resolver.ofEmail(req.getEmail().trim());
Defensive patterns

Strategy: validation

Validate before calling

if (!StringUtils.hasText(email) || !email.contains("@")) {
    throw new ServerWebInputException("A valid email is required");
}
var sub = resolver.ofEmail(email.trim());

Type guard

static boolean isPlausibleEmail(String s) {
    return s != null && !s.trim().isEmpty() && s.contains("@") && s.indexOf('@') > 0;
}

Try / catch

try {
    resolver.ofEmail(email);
} catch (IllegalArgumentException e) {
    throw new ServerWebInputException("Email must not be blank", null, e);
}

Prevention

When it happens

Trigger: Calling Subscription.Subscriber ofEmail(email) with a blank/null email string, e.g. from an unvalidated form field or an API request missing the email body.

Common situations: Notification subscription endpoints that don't validate the email; anonymous email-subscribe forms submitted empty; null passed programmatically due to a missing map key.

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/b0a9a86fa57f1ca5. Report an issue: GitHub.