{"record":{"id":"b0a9a86fa57f1ca5","repo":"halo-dev/halo","slug":"email-must-not-be-blank","errorCode":null,"errorMessage":"Email must not be blank","messagePattern":"Email must not be blank","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"warning","filePath":"application/src/main/java/run/halo/app/notification/DefaultSubscriberEmailResolver.java","lineNumber":40,"sourceCode":"@RequiredArgsConstructor\npublic class DefaultSubscriberEmailResolver implements SubscriberEmailResolver {\n    private final ReactiveExtensionClient client;\n\n    @Override\n    public Mono<String> resolve(Subscription.Subscriber subscriber) {\n        var identity = UserIdentity.of(subscriber.getName());\n        if (identity.isAnonymous()) {\n            return Mono.fromSupplier(() -> getEmail(subscriber));\n        }\n        return client.fetch(User.class, subscriber.getName())\n                .filter(user -> user.getSpec().isEmailVerified())\n                .mapNotNull(user -> user.getSpec().getEmail());\n    }\n\n    @Override\n    public Subscription.Subscriber ofEmail(String email) {\n        if (StringUtils.isBlank(email)) {\n            throw new IllegalArgumentException(\"Email must not be blank\");\n        }\n        var subscriber = new Subscription.Subscriber();\n        subscriber.setName(UserIdentity.anonymousWithEmail(email).name());\n        return subscriber;\n    }\n\n    String getEmail(Subscription.Subscriber subscriber) {\n        var identity = UserIdentity.of(subscriber.getName());\n        if (!identity.isAnonymous()) {\n            throw new IllegalStateException(\"The subscriber is not an anonymous subscriber\");\n        }\n        return identity.getEmail()\n                .filter(StringUtils::isNotBlank)\n                .orElseThrow(() -> new IllegalStateException(\"The subscriber does not have an email\"));\n    }\n}\n","sourceCodeStart":22,"sourceCodeEnd":57,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/notification/DefaultSubscriberEmailResolver.java#L22-L57","documentation":"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.","triggerScenarios":"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.","commonSituations":"Notification subscription endpoints that don't validate the email; anonymous email-subscribe forms submitted empty; null passed programmatically due to a missing map key.","solutions":["Validate the email is non-blank and well-formed before calling ofEmail.","Return a 400 to the client when the email field is missing.","Default to a required-field check in the form/controller.","Trim and reject empty strings upstream."],"exampleFix":"// before\nvar sub = resolver.ofEmail(req.getEmail()); // email null\n\n// after\nif (!StringUtils.hasText(req.getEmail()) || !req.getEmail().contains(\"@\")) {\n    return Mono.error(new ServerWebInputException(\"Valid email is required\"));\n}\nvar sub = resolver.ofEmail(req.getEmail().trim());","handlingStrategy":"validation","validationCode":"if (!StringUtils.hasText(email) || !email.contains(\"@\")) {\n    throw new ServerWebInputException(\"A valid email is required\");\n}\nvar sub = resolver.ofEmail(email.trim());","typeGuard":"static boolean isPlausibleEmail(String s) {\n    return s != null && !s.trim().isEmpty() && s.contains(\"@\") && s.indexOf('@') > 0;\n}","tryCatchPattern":"try {\n    resolver.ofEmail(email);\n} catch (IllegalArgumentException e) {\n    throw new ServerWebInputException(\"Email must not be blank\", null, e);\n}","preventionTips":["Validate email presence/format at the API boundary before resolving subscribers.","Trim user input and reject empty values early.","Use a shared email validator for all subscription endpoints."],"tags":["notification","subscriber","validation","email"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}