Skip to content

Commit 87b41ad

Browse files
committed
grpc-pb: Add InvalidProtobufError class
Signed-off-by: Johannes Zottele <[email protected]>
1 parent f894838 commit 87b41ad

File tree

3 files changed

+27
-7
lines changed

3 files changed

+27
-7
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2023-2025 JetBrains s.r.o and contributors. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.rpc.grpc
6+
7+
public sealed class GrpcError : RuntimeException {
8+
protected constructor(message: String) : super(message)
9+
protected constructor(message: String, cause: Throwable) : super(message, cause)
10+
}
11+
12+
13+
public class InvalidProtobufError(message: String) : GrpcError(message) {
14+
public companion object {
15+
internal fun missingRequiredField(messageName: String, fieldName: String) =
16+
InvalidProtobufError("Message '$messageName' is missing a required field: $fieldName")
17+
}
18+
}
19+

grpc/grpc-core/src/commonTest/kotlin/kotlinx/rpc/grpc/pb/ProtosTest.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import asInternal
1313
import encodeWith
1414
import invoke
1515
import kotlinx.io.Buffer
16+
import kotlinx.rpc.grpc.InvalidProtobufError
1617
import kotlinx.rpc.grpc.codec.MessageCodec
1718
import kotlinx.rpc.grpc.test.*
1819
import kotlinx.rpc.grpc.test.common.*
@@ -104,7 +105,7 @@ class ProtosTest {
104105

105106
@Test
106107
fun testRepeatedWithRequiredSubField() {
107-
assertFailsWith<IllegalStateException> {
108+
assertFailsWith<InvalidProtobufError> {
108109
RepeatedWithRequired {
109110
// we construct the message using the internal class,
110111
// so it is not invoking the checkRequired method on construction
@@ -116,7 +117,7 @@ class ProtosTest {
116117
@Test
117118
fun testPresenceCheckProto() {
118119
// Check a missing required field in a user-constructed message
119-
assertFailsWith<IllegalStateException> {
120+
assertFailsWith<InvalidProtobufError> {
120121
PresenceCheck {}
121122
}
122123

@@ -126,7 +127,7 @@ class ProtosTest {
126127
encoder.writeFloat(2, 1f)
127128
encoder.flush()
128129

129-
assertFailsWith<IllegalStateException> {
130+
assertFailsWith<InvalidProtobufError> {
130131
PresenceCheckInternal.CODEC.decode(buffer)
131132
}
132133
}
@@ -245,7 +246,7 @@ class ProtosTest {
245246

246247
@Test
247248
fun testOneOfRequiredSubField() {
248-
assertFailsWith<IllegalStateException> {
249+
assertFailsWith<InvalidProtobufError> {
249250
OneOfWithRequired {
250251
// we construct the message using the internal class,
251252
// so it is not invoking the checkRequired method on construction
@@ -276,7 +277,7 @@ class ProtosTest {
276277

277278
@Test
278279
fun testRecursiveReqNotSet() {
279-
assertFailsWith<IllegalStateException> {
280+
assertFailsWith<InvalidProtobufError> {
280281
val msg = RecursiveReq {
281282
rec = RecursiveReq {
282283
rec = RecursiveReq {
@@ -397,7 +398,7 @@ class ProtosTest {
397398
// we use the internal constructor to avoid a "missing required field" error during object construction
398399
val missingRequiredMessage = PresenceCheckInternal()
399400

400-
assertFailsWith<IllegalStateException> {
401+
assertFailsWith<InvalidProtobufError> {
401402
val msg = TestMap {
402403
messages = mapOf(
403404
2 to missingRequiredMessage

protoc-gen/src/main/kotlin/kotlinx/rpc/protobuf/ModelToKotlinCommonGenerator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,7 @@ class ModelToKotlinCommonGenerator(
586586

587587
requiredFields.forEach { field ->
588588
ifBranch(condition = "!presenceMask[${field.presenceIdx}]", ifBlock = {
589-
code("error(\"${declaration.name.simpleName} is missing required field: ${field.name}\")")
589+
code("throw kotlinx.rpc.grpc.InvalidProtobufError.missingRequiredField(\"${declaration.name.simpleName}\", \"${field.name}\")")
590590
})
591591
}
592592

0 commit comments

Comments
 (0)