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

Encoding value classes fails in Protocol Buffers

Open ScottPeterJohnson opened this issue 5 months ago • 2 comments

Describe the bug Attempting to encode value classes with default generated serializers fails using Protocol Buffers.

To Reproduce

fun main(){
    ProtoBuf {}.encodeToByteArray(Example(1))
}
@Serializable
@JvmInline
value class Example(val raw : Int)

Expected behavior Encodes correctly as the base type like e.g. json does. Currently gives: Exception in thread "main" kotlinx.serialization.SerializationException: No tag in stack for requested element at kotlinx.serialization.protobuf.internal.ProtobufTaggedBase.popTag(ProtobufTaggedBase.kt:55) at kotlinx.serialization.protobuf.internal.ProtobufTaggedEncoder.encodeInline(ProtobufTaggedEncoder.kt:178)

Possibly related: https://github.com/Kotlin/kotlinx.serialization/issues/1774

Workaround: Write a custom serializer:

fun main(){
    ProtoBuf {}.encodeToByteArray(Example(1))
}

@JvmInline
@Serializable(with = ExampleSerializer::class)
value class Example(val raw : Int)
object ExampleSerializer : KSerializer<Example> {
    override val descriptor: SerialDescriptor
        get() = Int.serializer().descriptor
    override fun serialize(
        encoder: Encoder,
        value: Example
    ) {
        encoder.encodeInt(value.raw)
    }

    override fun deserialize(decoder: Decoder): Example {
        return Example(decoder.decodeInt())
    }
}

Environment

  • Kotlin version: 2.2.0
  • Library version: 1.9.0
  • Kotlin platforms: JVM
  • Gradle version: 8

ScottPeterJohnson avatar Jul 14 '25 13:07 ScottPeterJohnson

I reproduced the issue. Our protobuf encoder is not capable of serializing inline value classes as top-level objects, only as other objects fields. Which is definitely a bug.

fzhinkin avatar Aug 20 '25 20:08 fzhinkin

Seems like it won't be a simple fix as I initially thought:

  • we need to figure out how to deal with Proto<Something>-annotated fields of inline value classes
  • the same as above, but for the case of nested inline values classes
  • potentially, there might be the same issues for inline values classes that are fields of regular classes, we have to figure out something there too
  • Kotlin might start supporting multi-field value classes at some point, it's worth considering them when addressing single-field value classes issue

fzhinkin avatar Aug 21 '25 16:08 fzhinkin