{"record":{"id":"d80f821130ac60c6","repo":"halo-dev/halo","slug":"validation-error-email-pattern","errorCode":"validation.error.email.pattern","errorMessage":"validation.error.email.pattern","messagePattern":"validation\\.error\\.email\\.pattern","errorType":"validation","errorClass":"ServerWebInputException","httpStatus":400,"severity":"error","filePath":"application/src/main/java/run/halo/app/core/endpoint/console/UserEndpoint.java","lineNumber":324,"sourceCode":"    /**\n     * Payload for verifying an email address by code.\n     *\n     * @param password current password of the authenticated user\n     * @param code email verification code\n     */\n    public record VerifyCodeRequest(\n            @Schema(requiredMode = REQUIRED) String password,\n\n            @Schema(requiredMode = REQUIRED, minLength = 1) String code) {}\n\n    private Mono<ServerResponse> sendEmailVerificationCode(ServerRequest request) {\n        var emailMono = request.bodyToMono(EmailVerifyRequest.class)\n                .switchIfEmpty(Mono.error(() -> new ServerWebInputException(\"Request body is required.\")))\n                .doOnNext(emailReq -> {\n                    var bindingResult = ValidationUtils.validate(emailReq, validator, request.exchange());\n                    if (bindingResult.hasErrors()) {\n                        // only email field is validated\n                        throw new ServerWebInputException(\"validation.error.email.pattern\");\n                    }\n                })\n                .map(EmailVerifyRequest::email)\n                .map(String::toLowerCase);\n        return Mono.zip(emailMono, getAuthenticatedUserName())\n                .flatMap(tuple -> {\n                    var email = tuple.getT1();\n                    var username = tuple.getT2();\n                    return Mono.just(username)\n                            .transformDeferred(sendEmailVerificationCodeRateLimiter(username))\n                            .flatMap(u -> emailVerificationService.sendVerificationCode(username, email))\n                            .onErrorMap(RequestNotPermitted.class, RateLimitExceededException::new);\n                })\n                .then(ServerResponse.ok().build());\n    }\n\n    <T> RateLimiterOperator<T> verificationEmailRateLimiter(String username) {\n        String rateLimiterKey = \"verify-email-\" + username;","sourceCodeStart":306,"sourceCodeEnd":342,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/core/endpoint/console/UserEndpoint.java#L306-L342","documentation":"Thrown as a ServerWebInputException (HTTP 400) with code 'validation.error.email.pattern' by UserEndpoint.sendEmailVerificationCode. The EmailVerifyRequest body is run through bean validation; if the email field fails its @Email/@Pattern constraint, the message 'validation.error.email.pattern' is thrown. The string is intentionally an i18n code, not human text, so the frontend can localize it.","triggerScenarios":"POST /apis/api.console.halo.run/v1alpha1/users/-/send-email-verification-code with a JSON body whose 'email' is missing, empty, or malformed (e.g. 'foo@@bar', 'not-an-email', 'user@'). ValidationUtils.validate reports errors on the email field.","commonSituations":"Frontend validation bypassed; user typed an invalid email; a migration/import script sends raw unvalidated emails; testing with placeholder strings like 'test' or 'N/A'.","solutions":["Validate the email client-side (RFC-ish regex or HTML5 type=email) before posting the request.","Send a well-formed email string in the JSON body 'email' field, e.g. 'user@example.com'.","Map the response code 'validation.error.email.pattern' to a localized user-facing message in the UI."],"exampleFix":"// before\n//   { \"email\": \"foo@@bar\" }\n// after\n//   { \"email\": \"user@example.com\" }","handlingStrategy":"validation","validationCode":"// validate email before calling sendEmailVerificationCode\nprivate static final Pattern EMAIL =\n    Pattern.compile(\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\");\nif (!EMAIL.matcher(email).matches()) {\n    showUserError(\"Enter a valid email address\");\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate email format in the UI (HTML5 type=email + regex) before submit.","Map response code 'validation.error.email.pattern' to a localized message."],"tags":["user","email","validation","i18n","webflux"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}