apereo/cas · warning
Notification [ ] sent to [ ] rejected with error: [ ]
Error message
Notification [{}] sent to [{}] rejected with error: [{}] What it means
APNMessagingNotificationSender sends a push notification via the ApnsClient and inspects the async response. If Apple's APNs rejects the notification, it warns 'Notification [{}] sent to [{}] rejected with error: [{}]' with the rejection reason (e.g. BadDeviceToken, TopicDisallowed). The message was delivered to APNs but not accepted for delivery.
Solutions
- Read the rejection reason in the log and act on it (BadDeviceToken → remove/refresh the device token)
- Verify the APNs topic matches the iOS app bundle id and the signing key/team configuration
- Ensure device tokens are current and re-registered by the app
- Check you are using the correct APNs environment (development vs production) endpoint/credentials
Example fix
// before cas.notifications.apn.topic=com.old.bundle // after cas.notifications.apn.topic=com.example.correctbundle
Defensive patterns
Strategy: try-catch
Validate before calling
// pre-send sanity checks
if (!StringUtils.hasText(deviceToken) || deviceToken.length() < 32) return;
if (!StringUtils.hasText(apnsProperties.getTopic())) throw new IllegalStateException("APNs topic required"); Try / catch
apnsClient.sendNotification(n).whenComplete((resp, cause) -> {
if (cause != null) { LOGGER.error("APNs send failed", cause); }
else if (!resp.isAccepted()) { LOGGER.warn("APNs rejected: {}", resp.getRejectionReason()); }
}); Prevention
- Purge device tokens after BadDeviceToken rejections
- Keep topic aligned with the app bundle id
- Use correct environment keys (dev vs prod)
- Re-register tokens on app updates
When it happens
Trigger: apnsClient.sendNotification completes with a response where isAccepted() is false; the rejection reason from APNs (invalid device token, wrong topic/bundle id, expired token, payload issues) is logged.
Common situations: Stale device tokens for users who uninstalled the app, mismatched APNs topic vs the app's bundle identifier, wrong signing key/team settings, or environment mismatch (development token sent to production APNs).
AI-assisted analysis of apereo/cas@e7288fc434 (2026-09-08).
Data as JSON: /api/errors/398c36df848660b8.
Report an issue: GitHub.
Appendix: source
Thrown at support/cas-server-support-notifications-apn/src/main/java/org/apereo/cas/notifications/APNMessagingNotificationSender.java:46
@Override
@SuppressWarnings("FutureReturnValueIgnored")
public boolean notify(final Principal principal, final Map<String, String> messageData) {
val deviceToken = principal.getSingleValuedAttribute(properties.getRegistrationTokenAttributeName(), String.class);
val payload = new SimpleApnsPayloadBuilder()
.setAlertTitle(messageData.get("title"))
.setAlertBody(messageData.get("message"))
.build();
val pushNotification = new SimpleApnsPushNotification(deviceToken, properties.getTopic(), payload);
LOGGER.trace("Sending push notification to [{}] with payload [{}]", principal, pushNotification);
apnsClient.sendNotification(pushNotification)
.whenComplete((response, cause) -> {
if (response != null) {
if (response.isAccepted()) {
LOGGER.debug("Notification [{}] sent to [{}] is accepted successfully", pushNotification, principal.getId());
} else {
LOGGER.warn("Notification [{}] sent to [{}] rejected with error: [{}]",
pushNotification, principal.getId(), response.getRejectionReason().orElse(StringUtils.EMPTY));
}
} else {
LoggingUtils.error(LOGGER, cause);
}
});
return true;
}
}
View on GitHub (pinned to e7288fc434)