Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.4k stars 620 forks source link

1.7.2 builtin UUID serializer breaks compatibility with gradle #2803

Closed mgroth0 closed 1 month ago

mgroth0 commented 2 months ago

Gradle ships with a specific Kotlin version, and Gradle version 8.8 is the newest gradle version that is verified compatible with kotlin 2.0.20. However, Gradle 8.8 itself in its buildscript and settings script runs Kotlin version 1.9.22 as can be seen by printing KotlinVersion.CURRENT in a build.gradle.kts script.

If a gradle plugin author tries to include serialization plugin 1.7.1, everything works fine. But upon upgrading to 1.7.2, we are immediately hit with a runtime error during a gradle build:

Caused by: java.lang.NoClassDefFoundError: kotlin/uuid/Uuid
    at kotlinx.serialization.internal.PrimitivesKt.<clinit>(Primitives.kt:20)
    at kotlinx.serialization.descriptors.SerialDescriptorsKt.PrimitiveSerialDescriptor(SerialDescriptors.kt:91)

This error is unavoidable, as the serialization plugin attempts to load the new kotlin UUID class regardless of whether or not the consumer is trying to serialize or deserialize a UUID.

To Reproduce

  1. Write a gradle plugin which depends on serialization 1.7.2
  2. Apply that gradle plugin in a project using Gradle 8.8
  3. In the buildscript, settings script, or in the plugin itself, attempt to serialize or deserialize something
  4. Observe error

Expected behavior

I think its ok for consumers of get a runtime error if they try to serialize or deserialize a kotlin.uuid.UUID in a gradle build. In that case, of course the UUID class will not be available. But for this whole library to fail seems unnecessary. Making the loading of the UUID class conditional on whether or not it is used would retain backwards compatibility in the library.

sandwwraith commented 2 months ago

Hm, normally, 1.7.x versions shouldn't work with Kotlin 1.9 because the compiler should reject them (release notes explain why. Does Gradle uses 2.0.20 compiler to compile buildscript, but then Kotlin 1.9 to run? Why there are no compiler errors about Your current Kotlin version is 1.9.22, while kotlinx.serialization core runtime 1.7.2 requires at least Kotlin 2.0.0-RC1. Please update your Kotlin compiler and IDE plugin?

mgroth0 commented 2 months ago

Good question. But regardless of what gradle compiles buildscripts with, gradle plugins can compile with serialization 1.7.X and kotlin 2.0.20 and run fine on gradle 8.8 until serialization 1.7.2.

martinbonnin commented 1 month ago

Minimal reproducer:

import kotlinx.serialization.serializerOrNull

buildscript {
  dependencies {
    classpath("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2")
  }

  repositories {
    mavenCentral()
  }
}

@OptIn(kotlinx.serialization.InternalSerializationApi::class)
println(Float::class.serializerOrNull())

Does Gradle uses 2.0.20 compiler to compile buildscript, but then Kotlin 1.9 to run

I believe Gradle uses 1.9 to compile and forces 1.9 at runtime. Because there is n+1 forward compatibility, it compiles fine.

Why there are no compiler errors

Looks like the error is triggered from the serialization compiler plugin? It might not be always applied.

pdvrieze commented 1 month ago

A very important thing to serialize is that in gradle buildSrc is special, and classes added to the classpath there are added to a very high level class loader (thus can not be overridden/specified in the project itself). This basically creates a Kotlin plugin version conflict. There is a workaround, use includeBuild instead and have that define a plugin (for the project) that is applied like a normal plugin. You can then build the plugin with gradle's Kotlin version, and then use it with a newer kotlin plugin version. See also: https://discuss.gradle.org/t/different-behaivor-between-buildsrc-and-include-build-build-logic/47705 and https://discuss.gradle.org/t/different-behaivor-between-buildsrc-and-include-build-build-logic/47705

mny459 commented 1 month ago

same error

kotlin 2.0.10 kotlinx.serialization 1.7.1 or 1.7.2 ktor: 3.0.0-rc-1

cyberkaidev commented 1 month ago

I have the same problem: Your current Kotlin version is 1.9.0, while kotlinx.serialization core runtime 1.7.1 requires at least Kotlin 2.0.0-RC1. Please update your Kotlin compiler and IDE plugin.

cyberkaidev commented 1 month ago

I fixed it just by changing the version: org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0