apereo/cas · warning

No recipient is provided with a valid email/phone for

Error message

No recipient is provided with a valid email/phone for %s

What it means

REST endpoint PasswordManagementEndpoint.passwordReset resolves the user's email addresses and phone from the configured password-management service. If both come back empty it logs this warn and returns HTTP 422 (Unprocessable Content) with the message, refusing to generate a reset link because there is nowhere to send it.

Solutions

  1. Populate a valid mail (and/or phone) attribute for the user in the backend store
  2. Verify cas.authn.pm.reset.mail.attributeName and sms.attributeName match real populated attributes
  3. Check upstream warns from findEmails/findAttribute (invalid email / missing LDAP attribute) to see which check failed
  4. For programmatic flows, handle the 422 response and prompt for an alternate contact or admin-assisted reset

Example fix

// before — user entry lacks mail
// HTTP 422 No recipient is provided with a valid email/phone for jsmith
// after — populate LDAP: mail: jsmith@example.com
// endpoint then returns 200 with reset instructions sent
Defensive patterns

Strategy: validation

Validate before calling

if (emails.isEmpty() && StringUtils.isBlank(phone)) {
    // handle HTTP 422 Unprocessable Content from PasswordManagementEndpoint
    promptForAlternateContact(username);
}

Try / catch

ResponseEntity<String> r = restTemplate.postForEntity(resetUrl, req, String.class);
if (r.getStatusCode().value() == 422) {
    log.warn("No valid recipient for reset: {}", r.getBody());
}

Prevention

When it happens

Trigger: passwordManagementService.findEmails(query) returns an empty set AND findPhone(query) returns null/blank for the submitted username — i.e. the configured mail/sms attributes are absent or invalid in the backend for that user.

Common situations: User has no mail/mobile attributes in LDAP; PM mail attribute misconfigured; PM service is the no-op or LDAP search returns no entry; calling the REST endpoint directly during integration testing with test users lacking contact attributes.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08). Data as JSON: /api/errors/fa0f2702eab2342c. Report an issue: GitHub.

Appendix: source

Thrown at support/cas-server-support-pm-webflow/src/main/java/org/apereo/cas/pm/web/PasswordManagementEndpoint.java:166

     *
     * @return the response entity
     */
    @Operation(summary = "Initiate a password reset operation and notify the user",
        parameters = {
            @Parameter(name = "username", description = "The username to reset the password for"),
            @Parameter(name = "service", description = "The service requesting the password reset")
        })
    @PostMapping(path = "/reset/requests/{username}", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity passwordReset(@PathVariable final String username,
                                        @RequestParam("service") final String service,
                                        final HttpServletRequest request) throws Throwable {
        val query = PasswordManagementQuery.builder().username(username).build();

        val emails = passwordManagementService.getObject().findEmails(query);
        val phone = passwordManagementService.getObject().findPhone(query);
        if (emails.isEmpty() && StringUtils.isBlank(phone)) {
            val message = "No recipient is provided with a valid email/phone for %s".formatted(username);
            LOGGER.warn(message);
            return ResponseEntity.unprocessableContent().body(message);
        }

        val webApplicationService = serviceFactory.getObject().createService(service);
        val registeredService = servicesManager.getObject().findServiceBy(webApplicationService);
        val principal = resolvedPrincipal(username);

        val audit = AuditableContext.builder()
            .registeredService(registeredService)
            .service(webApplicationService)
            .principal(principal)
            .httpRequest(request)
            .build();
        val accessResult = registeredServiceAccessStrategyEnforcer.getObject().execute(audit);
        accessResult.throwExceptionIfNeeded();

        val url = passwordResetUrlBuilder.getObject().build(username, webApplicationService);
        val pm = casProperties.getAuthn().getPm();

View on GitHub (pinned to e7288fc434)