Known limitations
The gRPC integration is under active development. This page lists current limitations that may affect your project.
Platform support
The following Kotlin targets are not supported:
Kotlin/JS
Kotlin/Wasm (both WasmJs and WasmWasi)
gRPC support is available for JVM, Android, Apple, and Linux targets. See Platforms for the full per-artifact matrix.
Protobuf code generation
- Field presence API is being redesigned
The way
optionalfields map to Kotlin types is being reworked. Currently, optional fields are generated with their default values and ahas<Field>()presence API. A future release will introduce Kotlin nullable types for optional fields, with extension properties likefieldOrDefaultto access default values when presence is not set. The exact API shape — including whether to default to nullable or non-nullable types, and how editions 2023+ (where all fields are implicitly optional) interact with this — is still under discussion.- Well-Known Types are not mapped to Kotlin types
Well-Known Types such as
google.protobuf.Timestamp,google.protobuf.Duration, andgoogle.protobuf.Emptyare generated as regular protobuf messages. They are not mapped to Kotlin equivalents likekotlinx.datetime.Instant,kotlin.time.Duration, orUnit.- Oneof field access is being redesigned
oneoffields are generated as Kotlin sealed classes and accessed through a wrapper property (e.g.message.either.success). A flatter access pattern (e.g.message.success) and a more ergonomic builder syntax are being explored, while preserving exhaustivewhenmatching as the primary usage pattern.- No kotlin_package option
The
kotlin_packagefile option is not supported. Generated code uses the package derived from the protopackagedeclaration.- No kotlin_multiple_files option
The
kotlin_multiple_filesfile option is not supported. All declarations from a single .proto file are generated into a single Kotlin file.- Decoded lists and maps are mutable
List and map fields in decoded messages are backed by mutable collections. Modifying them after decoding may lead to unexpected behavior.
- No message merging
There is no
mergeFromequivalent. To combine two messages, you must manually copy fields using the builder DSL.- No runtime access to field numbers
Proto field numbers are not exposed in the generated Kotlin API. If you need to work with raw field numbers at runtime, you must maintain the mapping manually.
- No descriptor-based reflection
Unlike protobuf-java, there is no runtime reflection API based on descriptors. Features like
Descriptors.Descriptor,Descriptors.FieldDescriptor, dynamic field access viagetField/setField, andDynamicMessageare not available. Generic proto processing, schema-driven validation, and dynamic message routing must be implemented using the generated static API.- No JSON encoding for protobuf messages
Protobuf messages can only be serialized in the binary wire format. JSON encoding (as specified by the proto3 JSON mapping) is not available.
- Unknown fields are not accessible
Unknown fields encountered during decoding are preserved and re-encoded, but there is no API to read or write them directly.
gRPC runtime
- No per-service or per-method interceptors
Client and server interceptors can only be applied globally. There is no way to attach an interceptor to a specific service or method.
- No per-service call options
GrpcCallOptions(such as deadlines and credentials) can only be set at the client level. Per-service configuration viawithServiceis not available.- No gRPC transcoding
REST-to-gRPC transcoding (as defined by
google.api.httpannotations) is not supported.
Java interoperability
- No compatibility with protobuf-java generated types
Generated Kotlin protobuf types are not compatible with protobuf-java or grpc-java generated types. If your project depends on Java libraries that accept or return protobuf-java
Messageinstances, you cannot passkotlinx.rpc-generated messages directly. Interop requires serializing to bytes on one side and deserializing on the other.- Calling generated code from Java may be inconvenient
The generated API is designed to be Kotlin-first. Kotlin-specific constructs such as extension properties, builder DSLs, and default parameter values may not translate well when called from Java. If your project has Java callers that need to work with generated protobuf types, you may need to write Kotlin wrapper functions to provide a Java-friendly API.
Gradle plugin
- Eager configuration in Gradle 9.0
The plugin eagerly resolves jar dependencies for the Buf CLI and protoc plugins, which triggers a configuration-time warning in Gradle 9.0 and later. The build still succeeds, but the warning may appear in your console output.