-
Notifications
You must be signed in to change notification settings - Fork 48
Description
Describe the bug
When creating an iOS installation using AppleInstallation via createOrUpdateInstallation(...), Azure Notification Hubs REST API returns:
'Platform' property is not specified or given value is not supported.
This occurs even though AppleInstallation is used and the platform is correctly set internally.
There appears to be an inconsistency between:
- AppleInstallation (which uses "apple" as platform internally in BaseInstallationDeserializer.java)
- NotificationPlatform.Apns (serialized as "apns")
- REST API validation expectations
The SDK serialization behavior does not align with the REST Installations API requirements.
Exception or Stack Trace
2026-02-24T10:26:42.3826749Z com.windowsazure.messaging.NotificationHubsException: Tracking ID: <id> Error: HTTP/2.0 400 Bad Request - <Error xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><Code>400</Code><Detail>The provided request body is invalid. Error: 'Platform' property is not specified or given value is not supported.. TrackingId:<id>,TimeStamp:2/24/2026 10:26:42 AM +00:00</Detail></Error>
2026-02-24T10:26:42.3826767Z at com.windowsazure.messaging.NotificationHubsService$1.completed(NotificationHubsService.java:69) ~[na:na]
2026-02-24T10:26:42.3827203Z at com.windowsazure.messaging.NotificationHubsService$1.completed(NotificationHubsService.java:63) ~[na:na]
2026-02-24T10:26:42.3827228Z at org.apache.hc.core5.concurrent.BasicFuture.completed(BasicFuture.java:148) ~[application:5.3.6]
2026-02-24T10:26:42.3827245Z at org.apache.hc.core5.concurrent.ComplexFuture.completed(ComplexFuture.java:72) ~[application:5.3.6]
2026-02-24T10:26:42.3827264Z at org.apache.hc.client5.http.impl.async.InternalAbstractHttpAsyncClient$2$1.completed(InternalAbstractHttpAsyncClient.java:321) ~[na:na]
2026-02-24T10:26:42.3827282Z at org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer$1.completed(AbstractAsyncResponseConsumer.java:101) ~[na:na]
2026-02-24T10:26:42.3827300Z at org.apache.hc.core5.http.nio.entity.AbstractBinAsyncEntityConsumer.completed(AbstractBinAsyncEntityConsumer.java:87) ~[application:5.3.6]
2026-02-24T10:26:42.3827319Z at org.apache.hc.core5.http.nio.entity.AbstractBinDataConsumer.streamEnd(AbstractBinDataConsumer.java:83) ~[application:5.3.6]
2026-02-24T10:26:42.3827337Z at org.apache.hc.core5.http.nio.support.AbstractAsyncResponseConsumer.streamEnd(AbstractAsyncResponseConsumer.java:142) ~[application:5.3.6]
2026-02-24T10:26:42.3827355Z at org.apache.hc.client5.http.impl.async.H2AsyncMainClientExec$1.streamEnd(H2AsyncMainClientExec.java:186) ~[na:na]
2026-02-24T10:26:42.3827450Z at org.apache.hc.core5.http2.impl.nio.ClientH2StreamHandler.consumeData(ClientH2StreamHandler.java:242) ~[na:na]
2026-02-24T10:26:42.3827471Z at org.apache.hc.core5.http2.impl.nio.AbstractH2StreamMultiplexer$H2Stream.consumeData(AbstractH2StreamMultiplexer.java:1661) ~[na:na]
2026-02-24T10:26:42.3827489Z at org.apache.hc.core5.http2.impl.nio.AbstractH2StreamMultiplexer.consumeDataFrame(AbstractH2StreamMultiplexer.java:1051) ~[application:5.3.6]
2026-02-24T10:26:42.3827507Z at org.apache.hc.core5.http2.impl.nio.AbstractH2StreamMultiplexer.consumeFrame(AbstractH2StreamMultiplexer.java:740) ~[application:5.3.6]
2026-02-24T10:26:42.3827525Z at org.apache.hc.core5.http2.impl.nio.AbstractH2StreamMultiplexer.onInput(AbstractH2StreamMultiplexer.java:448) ~[application:5.3.6]
2026-02-24T10:26:42.3827545Z at org.apache.hc.core5.http2.impl.nio.AbstractH2IOEventHandler.inputReady(AbstractH2IOEventHandler.java:65) ~[application:5.3.6]
2026-02-24T10:26:42.3827562Z at org.apache.hc.core5.http2.impl.nio.ClientH2IOEventHandler.inputReady(ClientH2IOEventHandler.java:39) ~[na:na]
2026-02-24T10:26:42.3827580Z at org.apache.hc.core5.reactor.ssl.SSLIOSession.decryptData(SSLIOSession.java:618) ~[application:5.3.6]
2026-02-24T10:26:42.3827597Z at org.apache.hc.core5.reactor.ssl.SSLIOSession.access$200(SSLIOSession.java:74) ~[application:5.3.6]
2026-02-24T10:26:42.3827614Z at org.apache.hc.core5.reactor.ssl.SSLIOSession$1.inputReady(SSLIOSession.java:204) ~[na:na]
2026-02-24T10:26:42.3827684Z at org.apache.hc.core5.reactor.InternalDataChannel.onIOEvent(InternalDataChannel.java:139) ~[na:na]
2026-02-24T10:26:42.3827702Z at org.apache.hc.core5.reactor.InternalChannel.handleIOEvent(InternalChannel.java:51) ~[application:5.3.6]
2026-02-24T10:26:42.3827717Z at org.apache.hc.core5.reactor.SingleCoreIOReactor.processEvents(SingleCoreIOReactor.java:176) ~[na:na]
2026-02-24T10:26:42.3827735Z at org.apache.hc.core5.reactor.SingleCoreIOReactor.doExecute(SingleCoreIOReactor.java:125) ~[na:na]
2026-02-24T10:26:42.3827752Z at org.apache.hc.core5.reactor.AbstractSingleCoreIOReactor.execute(AbstractSingleCoreIOReactor.java:92) ~[application:5.3.6]
2026-02-24T10:26:42.3827768Z at org.apache.hc.core5.reactor.IOReactorWorker.run(IOReactorWorker.java:44) ~[na:na]
2026-02-24T10:26:42.3827956Z at java.base@25.0.2/java.lang.Thread.runWith(Thread.java:1487) ~[application:na]
2026-02-24T10:26:42.3827977Z at java.base@25.0.2/java.lang.Thread.run(Thread.java:1474) ~[application:na]
2026-02-24T10:26:42.3827995Z at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:832) ~[application:na]
2026-02-24T10:26:42.3828070Z at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:808) ~[application:na]
2026-02-24T10:26:42.3828084Z
To Reproduce
Steps to reproduce the behavior:
- Spring boot 4/GraalVM native image
- Create an AppleInstallation
- Call createOrUpdateInstallation(...)
- Receive validation error from service
Code Snippet
public void registerDevice(String installationId, String deviceToken,
String userId, List<String> tags) {
try {
AppleInstallation installation = new AppleInstallation(installationId);
installation.setPushChannel(deviceToken);
if (tags != null && !tags.isEmpty()) {
for (String tag : tags) {
installation.addTag(tag);
}
}
if (userId != null && !userId.isEmpty()) {
installation.setUserId(userId);
}
hub().createOrUpdateInstallation(installation);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
Expected behavior
The installation should be successfully created when using AppleInstallation with a valid APNS device token.
The SDK should serialize the platform value in a way that is accepted by the Notification Hubs Installations REST API.
Setup (please complete the following information):
- OS: Linux (Docker container)
- Framework: Spring Boot 4/Maven (native image build)
- Build: GraalVM 25 Community (native image, built via Dockerfile)
- IDE: IntelliJ IDEA
- Library: com.github.Azure:azure-notificationhubs-java-backend:1.0.5 (GitHub/JitPack-style build)
Additional context
Add any other context about the problem here.
Information Checklist
Kindly make sure that you have added all the following information above and checkoff the required fields otherwise we will treat the issue as an incomplete report. Please do not provide any private information in this bug report.
- Bug Description Added
- Repro Steps Added
- Setup information Added