kotlinx.serialization icon indicating copy to clipboard operation
kotlinx.serialization copied to clipboard

IndexOutOfBoundsException on Generics Subclass Serialization

Open CloudyDino opened this issue 3 years ago • 3 comments

Describe the bug I'm trying to create a generic class called Event that takes in a generic serializable payload and can be converted into Json. I'd prefer this so I can eventually pass the code into a function that takes in an object of type Event and serializes it for a call. Something like this:

object EventPublisher {
    private val client = HttpClient(CIO)

    suspend fun <reified T>  publish(event: Event<T>) {
        client.post("http://127.0.0.1:8080/events") {
            setBody(event)
        }
    }
}

so I can publish events of all types from my app.

To Reproduce The following is what gives the error:

@Serializable
sealed class Event<T>(
    val message: String,
    val payload: T
) {
    
    @Serializable
    data class UserCreated(
        val user: User,
    ) : Event<User>(
        "User created",
        user
    )
}

@Serializable
data class User(
    val id: String,
    val name: String
)

fun main() {
    val user = User("id", "Alice")
    println(Json.encodeToString(Event.UserCreated(user)))
}

The two following code snippets seem identical to the one above, but seem to not cause any error:

@Serializable
sealed class Event<T>(
    val message: String,
    val payload: T
) {
    @Serializable
    class UserCreated<T>(
        private val user: T
    ) : Event<T>("StringEvent", user) where T : User
}


@Serializable
data class User(
    val id: String,
    val name: String
)

fun main() {
    val user = User("id", "Alice")
    println(Json.encodeToString(Event.UserCreated(user)))
}
@Serializable
sealed class Event<T>(
    val message: String,
) {
    abstract val payload: T

    @Serializable
    data class UserCreated(
        val user: User,
    ) : Event<User>(
        "User created"
    ) {
        override val payload = user
    }
}

@Serializable
data class User(
    val id: String,
    val name: String
)

fun main() {
    val user = User("id", "Alice")
    println(Json.encodeToString(Event.UserCreated(user)))
}

Expected behavior Compile and work just like the working examples I provided.

Environment

  • Kotlin version: 1.6.10
  • Kotlin platforms: JVM
  • Gradle version: 7.2
  • Plugin: id("org.jetbrains.kotlin.plugin.serialization") version "1.6.20-M1"
  • Dependencies:
implementation(platform("io.ktor:ktor-bom:2.0.0-beta-1"))
implementation("io.ktor:ktor-client-core")
implementation("io.ktor:ktor-client-content-negotiation")
implementation("io.ktor:ktor-client-serialization")
implementation("io.ktor:ktor-client-cio")

CloudyDino avatar Feb 23 '22 22:02 CloudyDino

Is the issue still actual? Can you attach stacktrace?

sandwwraith avatar Mar 29 '22 13:03 sandwwraith

Here is the full code with imports:

import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

@Serializable
sealed class Event<T>(
    val message: String,
    val payload: T
) {

    @Serializable
    data class UserCreated(
        val user: User,
    ) : Event<User>(
        "User created",
        user
    )
}

@Serializable
data class User(
    val id: String,
    val name: String
)

fun main() {
    val user = User("id", "Alice")
    println(Json.encodeToString(Event.UserCreated(user)))
}

and here is the stacktrace:

java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
	at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
	at java.base/java.util.Objects.checkIndex(Objects.java:372)
	at java.base/java.util.ArrayList.get(ArrayList.java:459)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator$formEncodeDecodePropertyCall$1.invoke(SerializerIrGenerator.kt:295)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator$formEncodeDecodePropertyCall$1.invoke(SerializerIrGenerator.kt:288)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.IrBuilderExtension$DefaultImpls.serializerInstance(GeneratorHelpers.kt:919)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator.serializerInstance(SerializerIrGenerator.kt:47)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.IrBuilderExtension$DefaultImpls.formEncodeDecodePropertyCall(GeneratorHelpers.kt:1315)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator.formEncodeDecodePropertyCall(SerializerIrGenerator.kt:47)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator.formEncodeDecodePropertyCall(SerializerIrGenerator.kt:288)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator$generateLoad$1.invoke(SerializerIrGenerator.kt:383)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator$generateLoad$1.invoke(SerializerIrGenerator.kt:324)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.IrBuilderExtension$DefaultImpls.contributeFunction(GeneratorHelpers.kt:69)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator.contributeFunction(SerializerIrGenerator.kt:47)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.IrBuilderExtension$DefaultImpls.contributeFunction$default(GeneratorHelpers.kt:63)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator.generateLoad(SerializerIrGenerator.kt:324)
	at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen.generateLoadIfNeeded(SerializerCodegen.kt:116)
	at org.jetbrains.kotlinx.serialization.compiler.backend.common.SerializerCodegen.generate(SerializerCodegen.kt:38)
	at org.jetbrains.kotlinx.serialization.compiler.backend.ir.SerializerIrGenerator$Companion.generate(SerializerIrGenerator.kt:573)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializerClassLowering.lower(SerializationLoweringExtension.kt:59)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:36)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:44)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:55)
	at org.jetbrains.kotlin.ir.declarations.IrClass.acceptChildren(IrClass.kt:60)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoidKt.acceptChildrenVoid(IrElementVisitorVoid.kt:275)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:37)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:44)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:55)
	at org.jetbrains.kotlin.ir.declarations.IrClass.acceptChildren(IrClass.kt:60)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoidKt.acceptChildrenVoid(IrElementVisitorVoid.kt:275)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:37)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:44)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:55)
	at org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl.acceptChildren(IrFileImpl.kt:84)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoidKt.acceptChildrenVoid(IrElementVisitorVoid.kt:275)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitElement(SerializationLoweringExtension.kt:32)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitPackageFragment(IrElementVisitorVoid.kt:30)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitPackageFragment(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:37)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:38)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl.accept(IrFileImpl.kt:81)
	at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoidKt.acceptVoid(IrElementVisitorVoid.kt:271)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt.runOnFileInOrder(SerializationLoweringExtension.kt:30)
	at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtension.generate(SerializationLoweringExtension.kt:77)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr$lambda-1(JvmIrCodegenFactory.kt:121)
	at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:88)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:146)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr$default(JvmIrCodegenFactory.kt:64)
	at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.generateModule(JvmIrCodegenFactory.kt:59)
	at org.jetbrains.kotlin.codegen.KotlinCodegenFacade.compileCorrectFiles(KotlinCodegenFacade.java:35)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.generate(KotlinToJVMBytecodeCompiler.kt:331)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:123)
	at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:58)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:170)
	at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:52)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:92)
	at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:44)
	at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:98)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:434)
	at org.jetbrains.kotlin.incremental.IncrementalJvmCompilerRunner.runCompiler(IncrementalJvmCompilerRunner.kt:120)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally(IncrementalCompilerRunner.kt:357)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileIncrementally$default(IncrementalCompilerRunner.kt:299)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compileImpl(IncrementalCompilerRunner.kt:159)
	at org.jetbrains.kotlin.incremental.IncrementalCompilerRunner.compile(IncrementalCompilerRunner.kt:80)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.execIncrementalCompiler(CompileServiceImpl.kt:622)
	at org.jetbrains.kotlin.daemon.CompileServiceImplBase.access$execIncrementalCompiler(CompileServiceImpl.kt:100)
	at org.jetbrains.kotlin.daemon.CompileServiceImpl.compile(CompileServiceImpl.kt:1713)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200)
	at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at java.base/java.lang.Thread.run(Thread.java:829)

CloudyDino avatar Mar 29 '22 14:03 CloudyDino

I'm having the same Problem

JHarzenetter avatar Jul 07 '22 12:07 JHarzenetter

Are there any work arounds currently?

manuqiao avatar Sep 26 '22 09:09 manuqiao

No, nothing in particular

sandwwraith avatar Sep 26 '22 15:09 sandwwraith

Duplicate of #1264

sandwwraith avatar Oct 04 '22 16:10 sandwwraith