Skip to content

InvalidMutabilityException when deserializing objects with UNKNOWN fields #1502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
minaEweida opened this issue May 19, 2021 · 2 comments
Closed

Comments

@minaEweida
Copy link

This is happening when running for native when class is frozen, if you are deserializing a json that have UNKNOWN fields (which should be common in a non strict handling given that we might not want to deserialize some fields from a json response).

I see here which is added 6 days ago could be mutating the map in DescriptorSchemaCache.

val alternativeNamesMap = json.schemaCache.getOrPut(this, JsonAlternativeNamesKey, this::buildAlternativeNamesMap)

To Reproduce
If you run native for the test below it will fail with an InvalidMutabilityException.

class SerializerMutationTest {
    private val jsonNonStrict: Json by lazy {
        Json {
            isLenient = true
            ignoreUnknownKeys = true
            allowSpecialFloatingPointValues = true
            encodeDefaults = true
            useArrayPolymorphism = true
        }
    }

    @Test
    fun testDeserializeWithExtraFields() {
        freeze() // simulating a frozen environment
        val boxWithExtras = """
            {"width":25,"height":30,"color": "green"}
        """.trimIndent()
        val box = Box(25, 30)
        assertEquals(box, jsonNonStrict.decodeFromString(Box.serializer(), boxWithExtras))
    }
}

@Serializable
data class Box(
    val width: Int,
    val height: Int
)

Expected behavior
If I run this on 1.1.0 it passes. Is there a change that I missed in 1.2.1? Or is my configuration wrong?

Environment

  • Library version: 1.2.1
  • Kotlin platforms: Native
@Ribesg
Copy link

Ribesg commented May 19, 2021

I have this issue too while upgrading a huge KMP project from even older versions of everything, I'll try version 1.1.0 for now, thanks for this report :)

Here is a stacktrace I just got, seems to be matching:

kotlin.native.concurrent.InvalidMutabilityException: mutation attempt of frozen kotlin.collections.HashMap@16e90e8
    at 0   Event                               0x000000010b5fb3ef kfun:kotlin.Throwable#<init>(kotlin.String?){} + 95 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/Throwable.kt:23:37)
    at 1   Event                               0x000000010b5f3b6d kfun:kotlin.Exception#<init>(kotlin.String?){} + 93 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:44)
    at 2   Event                               0x000000010b5f3d4d kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 93 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:44)
    at 3   Event                               0x000000010b62ccfd kfun:kotlin.native.concurrent.InvalidMutabilityException#<init>(kotlin.String){} + 93 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/native/concurrent/Freezing.kt:22:60)
    at 4   Event                               0x000000010b62e4ff ThrowInvalidMutabilityException + 431 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:93:11)
    at 5   Event                               0x000000010b79a260 MutationCheck + 128
    at 6   Event                               0x000000010b60ec92 kfun:kotlin.collections.HashMap.<set-length>#internal + 82 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/collections/HashMap.kt:16:17)
    at 7   Event                               0x000000010b613a91 kfun:kotlin.collections.HashMap#addKey(1:0){}kotlin.Int + 1233 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/collections/HashMap.kt:292:36)
    at 8   Event                               0x000000010b60fe85 kfun:kotlin.collections.HashMap#put(1:0;1:1){}1:1? + 357 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/collections/HashMap.kt:68:21)
    at 9   Event                               0x000000010b85acd3 kfun:kotlinx.serialization.json.internal.DescriptorSchemaCache#set(kotlinx.serialization.descriptors.SerialDescriptor;kotlinx.serialization.json.internal.DescriptorSchemaCache.Key<0:0>;0:0){0§<kotlin.Any>} + 771 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/SchemaCache.kt:23:58)
    at 10  Event                               0x000000010b85b080 kfun:kotlinx.serialization.json.internal.DescriptorSchemaCache#getOrPut(kotlinx.serialization.descriptors.SerialDescriptor;kotlinx.serialization.json.internal.DescriptorSchemaCache.Key<0:0>;kotlin.Function0<0:0>){0§<kotlin.Any>}0:0 + 576 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/SchemaCache.kt:29:9)
    at 11  Event                               0x000000010b854d88 kfun:kotlinx.serialization.json.internal#getJsonNameIndex__at__kotlinx.serialization.descriptors.SerialDescriptor(kotlinx.serialization.json.Json;kotlin.String){}kotlin.Int + 904 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/JsonNamesMap.kt:52:26)
    at 12  Event                               0x000000010b85db7e kfun:kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeObjectIndex#internal + 734 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt:130:36)
    at 13  Event                               0x000000010b85cba6 kfun:kotlinx.serialization.json.internal.StreamingJsonDecoder#decodeElementIndex(kotlinx.serialization.descriptors.SerialDescriptor){}kotlin.Int + 502 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt:75:30)
    at 14  Event                               0x000000010bc557f0 kfun:com.mypackage.User.$serializer#deserialize(kotlinx.serialization.encoding.Decoder){}com.mypackage.User + 4000 (/somewhere/User.kt:1:1)
    at 15  Event                               0x000000010b858dde kfun:kotlinx.serialization.json.internal#decodeSerializableValuePolymorphic__at__kotlinx.serialization.json.JsonDecoder(kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any?>}0:0 + 2798 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt:63:29)
    at 16  Event                               0x000000010b85be5a kfun:kotlinx.serialization.json.internal.StreamingJsonDecoder#decodeSerializableValue(kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any?>}0:0 + 202 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt:32:16)
    at 17  Event                               0x000000010b7f724d kfun:kotlinx.serialization.encoding.AbstractDecoder#decodeSerializableValue(kotlinx.serialization.DeserializationStrategy<0:0>;0:0?){0§<kotlin.Any?>}0:0 + 253 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/encoding/AbstractDecoder.kt:43:12)
    at 18  Event                               0x000000010b7f7c64 kfun:kotlinx.serialization.encoding.AbstractDecoder#decodeSerializableElement(kotlinx.serialization.descriptors.SerialDescriptor;kotlin.Int;kotlinx.serialization.DeserializationStrategy<0:0>;0:0?){0§<kotlin.Any?>}0:0 + 324 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/encoding/AbstractDecoder.kt:70:12)
    at 19  Event                               0x000000010b7f9b6f kfun:kotlinx.serialization.encoding.CompositeDecoder#decodeSerializableElement$default(kotlinx.serialization.descriptors.SerialDescriptor;kotlin.Int;kotlinx.serialization.DeserializationStrategy<0:0>;0:0?;kotlin.Int){0§<kotlin.Any?>}0:0 + 559 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/encoding/Decoding.kt:535:12)
    at 20  Event                               0x000000010b80217a kfun:kotlinx.serialization.internal.ListLikeSerializer#readElement(kotlinx.serialization.encoding.CompositeDecoder;kotlin.Int;1:2;kotlin.Boolean){} + 522 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt:80:39)
    at 21  Event                               0x000000010b80165d kfun:kotlinx.serialization.internal.AbstractCollectionSerializer#readElement$default(kotlinx.serialization.encoding.CompositeDecoder;kotlin.Int;1:2;kotlin.Boolean;kotlin.Int){} + 269 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt:51:24)
    at 22  Event                               0x000000010b8010be kfun:kotlinx.serialization.internal.AbstractCollectionSerializer#merge(kotlinx.serialization.encoding.Decoder;1:1?){}1:1 + 1518 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt:36:17)
    at 23  Event                               0x000000010b8012cc kfun:kotlinx.serialization.internal.AbstractCollectionSerializer#deserialize(kotlinx.serialization.encoding.Decoder){}1:1 + 204 (/opt/buildAgent/work/b2fef8360e1bcf3d/core/commonMain/src/kotlinx/serialization/internal/CollectionSerializers.kt:43:62)
    at 24  Event                               0x000000010b858dde kfun:kotlinx.serialization.json.internal#decodeSerializableValuePolymorphic__at__kotlinx.serialization.json.JsonDecoder(kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any?>}0:0 + 2798 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/Polymorphic.kt:63:29)
    at 25  Event                               0x000000010b85be5a kfun:kotlinx.serialization.json.internal.StreamingJsonDecoder#decodeSerializableValue(kotlinx.serialization.DeserializationStrategy<0:0>){0§<kotlin.Any?>}0:0 + 202 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/internal/StreamingJsonDecoder.kt:32:16)
    at 26  Event                               0x000000010b838951 kfun:kotlinx.serialization.json.Json#decodeFromString(kotlinx.serialization.DeserializationStrategy<0:0>;kotlin.String){0§<kotlin.Any?>}0:0 + 753 (/opt/buildAgent/work/b2fef8360e1bcf3d/formats/json/commonMain/src/kotlinx/serialization/json/Json.kt:95:28)
    at 27  Event                               0x000000010bb83949 kfun:io.ktor.client.features.json.serializer.KotlinxSerializer#read(io.ktor.client.call.TypeInfo;io.ktor.utils.io.core.Input){}kotlin.Any + 1081 (/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-features/ktor-client-json/ktor-client-serialization/common/src/io/ktor/client/features/json/serializer/KotlinxSerializer.kt:37:21)
    at 28  Event                               0x000000010bb80b95 kfun:io.ktor.client.features.json.JsonFeature.Feature.$install$lambda-1COROUTINE$1.invokeSuspend#internal + 2805 (/Users/administrator/Documents/agent/work/8d547b974a7be21f/ktor-client/ktor-client-features/ktor-client-json/common/src/io/ktor/client/features/json/JsonFeature.kt:161:53)
    at 29  Event                               0x000000010b61f180 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl#resumeWith(kotlin.Result<kotlin.Any?>){} + 800 (/Users/teamcity1/teamcity_work/290aee0e088a1666/runtime/src/main/kotlin/kotlin/coroutines/ContinuationImpl.kt:30:39)

@sandwwraith
Copy link
Member

Duplicate of #1450. You сan disable useAlternativeNames flag as a workaround

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants