The RowndEvent.data field is typed as Map<String, String?>, but the Hub sends events with nested JSON objects as values, causing deserialization to fail.
Error:
kotlinx.serialization.json.internal.JsonDecodingException: Expected JsonPrimitive, but had JsonObject as the serialized body of string at element: $.data
JSON input: {"id":null}
Message received from Hub:
{"type":"event","payload":{"event":"user_data","data":{"data":{"id":null}}}}
The value {"id":null} is a JSON object, not a string, so it can't be deserialized into Map<String, String?>.
This isn't causing any crashes, as a warning/error log is emitted, but it would be good to clean this up.
Example stack trace
postMessage: {"type":"event","payload":{"event":"user_data","data":{"data":{"id":null}}}}
2026-01-15 11:29:44.464 7433-7631 Rownd.hub com.awesomemoduleexample D Unparseable message (Ask Gemini)
kotlinx.serialization.json.internal.JsonDecodingException: Expected JsonPrimitive, but had JsonObject as the serialized body of string at element: $.data
JSON input: {"id":null}
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeTaggedString(TreeJsonDecoder.kt:577)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeTaggedString(TreeJsonDecoder.kt:36)
at kotlinx.serialization.internal.TaggedDecoder.decodeString(Tagged.kt:231)
at kotlinx.serialization.internal.StringSerializer.deserialize(Primitives.kt:131)
at kotlinx.serialization.internal.StringSerializer.deserialize(Primitives.kt:127)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:345)
at kotlinx.serialization.internal.NullableSerializer.deserialize(NullableSerializer.kt:30)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:345)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableValue(Tagged.kt:207)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement$lambda$1(Tagged.kt:279)
at kotlinx.serialization.internal.TaggedDecoder.$r8$lambda$DBYIndnlKB76_oyt-Ap4f_T35nM(Unknown Source:0)
at kotlinx.serialization.internal.TaggedDecoder$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0)
at kotlinx.serialization.internal.TaggedDecoder.tagBlock(Tagged.kt:294)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement(Tagged.kt:279)
at kotlinx.serialization.encoding.CompositeDecoder.decodeSerializableElement$default(Decoding.kt:539)
at kotlinx.serialization.internal.MapLikeSerializer.readElement(CollectionSerializers.kt:111)
at kotlinx.serialization.internal.MapLikeSerializer.readElement(CollectionSerializers.kt:84)
at kotlinx.serialization.internal.AbstractCollectionSerializer.readElement$default(CollectionSerializers.kt:51)
at kotlinx.serialization.internal.AbstractCollectionSerializer.merge(CollectionSerializers.kt:36)
at kotlinx.serialization.internal.AbstractCollectionSerializer.deserialize(CollectionSerializers.kt:43)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:345)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableValue(Tagged.kt:207)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement$lambda$1(Tagged.kt:279)
at kotlinx.serialization.internal.TaggedDecoder.$r8$lambda$DBYIndnlKB76_oyt-Ap4f_T35nM(Unknown Source:0)
at kotlinx.serialization.internal.TaggedDecoder$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0)
at kotlinx.serialization.internal.TaggedDecoder.tagBlock(Tagged.kt:294)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement(Tagged.kt:279)
at io.rownd.android.util.RowndEvent$$serializer.deserialize(RowndEvent.kt:40)
at io.rownd.android.util.RowndEvent$$serializer.deserialize(RowndEvent.kt:40)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:345)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableValue(Tagged.kt:207)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement$lambda$1(Tagged.kt:279)
at kotlinx.serialization.internal.TaggedDecoder.$r8$lambda$DBYIndnlKB76_oyt-Ap4f_T35nM(Unknown Source:0)
at kotlinx.serialization.internal.TaggedDecoder$$ExternalSyntheticLambda0.invoke(D8$$SyntheticClass:0)
at kotlinx.serialization.internal.TaggedDecoder.tagBlock(Tagged.kt:294)
at kotlinx.serialization.internal.TaggedDecoder.decodeSerializableElement(Tagged.kt:279)
at io.rownd.android.models.EventMessage$$serializer.deserialize(RowndHubInteropMessage.kt:166)
2026-01-15 11:29:44.467 7433-7631 Rownd.hub com.awesomemoduleexample D at io.rownd.android.models.EventMessage$$serializer.deserialize(RowndHubInteropMessage.kt:166) (Ask Gemini)
at kotlinx.serialization.json.internal.AbstractJsonTreeDecoder.decodeSerializableValue(TreeJsonDecoder.kt:345)
at kotlinx.serialization.json.internal.TreeJsonDecoderKt.readJson(TreeJsonDecoder.kt:25)
at kotlinx.serialization.json.Json.decodeFromJsonElement(Json.kt:170)
at kotlinx.serialization.json.JsonContentPolymorphicSerializer.deserialize(JsonContentPolymorphicSerializer.kt:94)
at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:69)
at kotlinx.serialization.json.Json.decodeFromString(Json.kt:149)
at io.rownd.android.views.RowndJavascriptInterface.postMessage(RowndWebView.kt:389)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loopOnce(Looper.java:161)
at android.os.Looper.loop(Looper.java:288)
at android.os.HandlerThread.run(HandlerThread.java:67)
The RowndEvent.data field is typed as Map<String, String?>, but the Hub sends events with nested JSON objects as values, causing deserialization to fail.
Error:
This isn't causing any crashes, as a warning/error log is emitted, but it would be good to clean this up.
Example stack trace