Skip to content

Commit c55326b

Browse files
authored
Merge pull request #3439 from square/bquenaudon.2025-10-16.ProtocolException
Improve ProtocolException's message
2 parents a43a239 + 58f09d5 commit c55326b

File tree

5 files changed

+36
-34
lines changed

5 files changed

+36
-34
lines changed

wire-runtime/src/commonMain/kotlin/com/squareup/wire/ByteArrayProtoReader32.kt

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ internal class ByteArrayProtoReader32(
129129
nextFieldEncoding = FieldEncoding.LENGTH_DELIMITED
130130
state = STATE_LENGTH_DELIMITED
131131
val length = internalReadVarint32()
132-
if (length < 0) throw ProtocolException("Negative length: $length")
132+
if (length < 0) throw ProtocolException("Negative length: $length. Reader position: $pos. Last read tag: $tag.")
133133
if (pushedLimit != -1) throw IllegalStateException()
134134
// Push the current limit, and set a new limit to the length of this value.
135135
pushedLimit = limit
@@ -148,7 +148,7 @@ internal class ByteArrayProtoReader32(
148148

149149
loop@ while (pos < limit) {
150150
val tagAndFieldEncoding = internalReadVarint32()
151-
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0")
151+
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0. Reader position: $pos. Last read tag: $tag.")
152152

153153
tag = tagAndFieldEncoding shr TAG_FIELD_ENCODING_BITS
154154
when (val groupOrFieldEncoding = tagAndFieldEncoding and FIELD_ENCODING_MASK) {
@@ -157,7 +157,7 @@ internal class ByteArrayProtoReader32(
157157
continue@loop
158158
}
159159

160-
STATE_END_GROUP -> throw ProtocolException("Unexpected end group")
160+
STATE_END_GROUP -> throw ProtocolException("Unexpected end group. Reader position: $pos. Last read tag: $tag.")
161161

162162
STATE_LENGTH_DELIMITED -> {
163163
internalNextLengthDelimited()
@@ -182,7 +182,7 @@ internal class ByteArrayProtoReader32(
182182
return tag
183183
}
184184

185-
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding")
185+
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding. Reader position: $pos. Last read tag: $tag.")
186186
}
187187
}
188188
return -1
@@ -207,7 +207,7 @@ internal class ByteArrayProtoReader32(
207207
private fun skipGroup(expectedEndTag: Int) {
208208
while (pos < limit) {
209209
val tagAndFieldEncoding = internalReadVarint32()
210-
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0")
210+
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0. Reader position: $pos. Last read tag: $tag.")
211211
val tag = tagAndFieldEncoding shr TAG_FIELD_ENCODING_BITS
212212
when (val groupOrFieldEncoding = tagAndFieldEncoding and FIELD_ENCODING_MASK) {
213213
STATE_START_GROUP -> {
@@ -224,7 +224,7 @@ internal class ByteArrayProtoReader32(
224224
}
225225
STATE_END_GROUP -> {
226226
if (tag == expectedEndTag) return // Success!
227-
throw ProtocolException("Unexpected end group")
227+
throw ProtocolException("Unexpected end group. Reader position: $pos. Last read tag: $tag.")
228228
}
229229
STATE_LENGTH_DELIMITED -> {
230230
val length = internalReadVarint32()
@@ -242,7 +242,7 @@ internal class ByteArrayProtoReader32(
242242
state = STATE_FIXED32
243243
readFixed32()
244244
}
245-
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding")
245+
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding. Reader position: $pos. Last read tag: $tag.")
246246
}
247247
}
248248
throw EOFException()
@@ -272,7 +272,7 @@ internal class ByteArrayProtoReader32(
272272
STATE_FIXED32,
273273
-> true // Not packed.
274274

275-
else -> throw ProtocolException("unexpected state: $state")
275+
else -> throw ProtocolException("unexpected state: $state. Reader position: $pos. Last read tag: $tag.")
276276
}
277277
}
278278

@@ -283,7 +283,7 @@ internal class ByteArrayProtoReader32(
283283

284284
override fun readVarint32(): Int {
285285
if (state != STATE_VARINT && state != STATE_LENGTH_DELIMITED) {
286-
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state")
286+
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
287287
}
288288
val result = internalReadVarint32()
289289
afterPackableScalar(STATE_VARINT)
@@ -320,7 +320,7 @@ internal class ByteArrayProtoReader32(
320320
return result
321321
}
322322
}
323-
throw ProtocolException("Malformed VARINT")
323+
throw ProtocolException("Malformed VARINT. Reader position: $pos. Last read tag: $tag.")
324324
}
325325
}
326326
}
@@ -330,7 +330,7 @@ internal class ByteArrayProtoReader32(
330330

331331
override fun readVarint64(): Long {
332332
if (state != STATE_VARINT && state != STATE_LENGTH_DELIMITED) {
333-
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state")
333+
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
334334
}
335335
var shift = 0
336336
var result: Long = 0
@@ -343,12 +343,12 @@ internal class ByteArrayProtoReader32(
343343
}
344344
shift += 7
345345
}
346-
throw ProtocolException("WireInput encountered a malformed varint")
346+
throw ProtocolException("WireInput encountered a malformed varint. Reader position: $pos. Last read tag: $tag.")
347347
}
348348

349349
override fun readFixed32(): Int {
350350
if (state != STATE_FIXED32 && state != STATE_LENGTH_DELIMITED) {
351-
throw ProtocolException("Expected FIXED32 or LENGTH_DELIMITED but was $state")
351+
throw ProtocolException("Expected FIXED32 or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
352352
}
353353
val result = readIntLe()
354354
afterPackableScalar(STATE_FIXED32)
@@ -357,7 +357,7 @@ internal class ByteArrayProtoReader32(
357357

358358
override fun readFixed64(): Long {
359359
if (state != STATE_FIXED64 && state != STATE_LENGTH_DELIMITED) {
360-
throw ProtocolException("Expected FIXED64 or LENGTH_DELIMITED but was $state")
360+
throw ProtocolException("Expected FIXED64 or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
361361
}
362362
val result = readLongLe()
363363
afterPackableScalar(STATE_FIXED64)
@@ -383,7 +383,7 @@ internal class ByteArrayProtoReader32(
383383

384384
private fun beforeLengthDelimitedScalar(): Int {
385385
if (state != STATE_LENGTH_DELIMITED) {
386-
throw ProtocolException("Expected LENGTH_DELIMITED but was $state")
386+
throw ProtocolException("Expected LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
387387
}
388388
val byteCount = limit - pos
389389
state = STATE_TAG

wire-runtime/src/commonMain/kotlin/com/squareup/wire/ProtoReader.kt

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ open class ProtoReader(private val source: BufferedSource) {
154154
nextFieldEncoding = FieldEncoding.LENGTH_DELIMITED
155155
state = STATE_LENGTH_DELIMITED
156156
val length = internalReadVarint32()
157-
if (length < 0) throw ProtocolException("Negative length: $length")
157+
if (length < 0) throw ProtocolException("Negative length: $length. Reader position: $pos. Last read tag: $tag.")
158158
if (pushedLimit != -1L) throw IllegalStateException()
159159
// Push the current limit, and set a new limit to the length of this value.
160160
pushedLimit = limit
@@ -179,7 +179,7 @@ open class ProtoReader(private val source: BufferedSource) {
179179

180180
loop@ while (pos < limit && !source.exhausted()) {
181181
val tagAndFieldEncoding = internalReadVarint32()
182-
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0")
182+
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0. Reader position: $pos. Last read tag: $tag.")
183183

184184
tag = tagAndFieldEncoding shr TAG_FIELD_ENCODING_BITS
185185
when (val groupOrFieldEncoding = tagAndFieldEncoding and FIELD_ENCODING_MASK) {
@@ -188,7 +188,7 @@ open class ProtoReader(private val source: BufferedSource) {
188188
continue@loop
189189
}
190190

191-
STATE_END_GROUP -> throw ProtocolException("Unexpected end group")
191+
STATE_END_GROUP -> throw ProtocolException("Unexpected end group. Reader position: $pos. Last read tag: $tag.")
192192

193193
STATE_LENGTH_DELIMITED -> {
194194
internalNextLengthDelimited()
@@ -213,7 +213,7 @@ open class ProtoReader(private val source: BufferedSource) {
213213
return tag
214214
}
215215

216-
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding")
216+
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding. Reader position: $pos. Last read tag: $tag.")
217217
}
218218
}
219219
return -1
@@ -246,7 +246,7 @@ open class ProtoReader(private val source: BufferedSource) {
246246
private fun skipGroup(expectedEndTag: Int) {
247247
while (pos < limit && !source.exhausted()) {
248248
val tagAndFieldEncoding = internalReadVarint32()
249-
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0")
249+
if (tagAndFieldEncoding == 0) throw ProtocolException("Unexpected tag 0. Reader position: $pos. Last read tag: $tag.")
250250
val tag = tagAndFieldEncoding shr TAG_FIELD_ENCODING_BITS
251251
when (val groupOrFieldEncoding = tagAndFieldEncoding and FIELD_ENCODING_MASK) {
252252
STATE_START_GROUP -> {
@@ -263,7 +263,7 @@ open class ProtoReader(private val source: BufferedSource) {
263263
}
264264
STATE_END_GROUP -> {
265265
if (tag == expectedEndTag) return // Success!
266-
throw ProtocolException("Unexpected end group")
266+
throw ProtocolException("Unexpected end group. Reader position: $pos. Last read tag: $tag.")
267267
}
268268
STATE_LENGTH_DELIMITED -> {
269269
val length = internalReadVarint32()
@@ -282,7 +282,7 @@ open class ProtoReader(private val source: BufferedSource) {
282282
state = STATE_FIXED32
283283
readFixed32()
284284
}
285-
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding")
285+
else -> throw ProtocolException("Unexpected field encoding: $groupOrFieldEncoding. Reader position: $pos. Last read tag: $tag.")
286286
}
287287
}
288288
throw EOFException()
@@ -322,7 +322,7 @@ open class ProtoReader(private val source: BufferedSource) {
322322
STATE_FIXED32,
323323
-> true // Not packed.
324324

325-
else -> throw ProtocolException("unexpected state: $state")
325+
else -> throw ProtocolException("unexpected state: $state. Reader position: $pos. Last read tag: $tag.")
326326
}
327327
}
328328

@@ -340,7 +340,7 @@ open class ProtoReader(private val source: BufferedSource) {
340340
@Throws(IOException::class)
341341
open fun readVarint32(): Int {
342342
if (state != STATE_VARINT && state != STATE_LENGTH_DELIMITED) {
343-
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state")
343+
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
344344
}
345345
val result = internalReadVarint32()
346346
afterPackableScalar(STATE_VARINT)
@@ -389,7 +389,7 @@ open class ProtoReader(private val source: BufferedSource) {
389389
return result
390390
}
391391
}
392-
throw ProtocolException("Malformed VARINT")
392+
throw ProtocolException("Malformed VARINT. Reader position: $pos. Last read tag: $tag.")
393393
}
394394
}
395395
}
@@ -401,7 +401,7 @@ open class ProtoReader(private val source: BufferedSource) {
401401
@Throws(IOException::class)
402402
open fun readVarint64(): Long {
403403
if (state != STATE_VARINT && state != STATE_LENGTH_DELIMITED) {
404-
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state")
404+
throw ProtocolException("Expected VARINT or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
405405
}
406406
var shift = 0
407407
var result: Long = 0
@@ -416,14 +416,14 @@ open class ProtoReader(private val source: BufferedSource) {
416416
}
417417
shift += 7
418418
}
419-
throw ProtocolException("WireInput encountered a malformed varint")
419+
throw ProtocolException("Malformed VARINT. Reader position: $pos. Last read tag: $tag.")
420420
}
421421

422422
/** Reads a 32-bit little-endian integer from the stream. */
423423
@Throws(IOException::class)
424424
open fun readFixed32(): Int {
425425
if (state != STATE_FIXED32 && state != STATE_LENGTH_DELIMITED) {
426-
throw ProtocolException("Expected FIXED32 or LENGTH_DELIMITED but was $state")
426+
throw ProtocolException("Expected FIXED32 or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
427427
}
428428
source.require(4) // Throws EOFException if insufficient bytes are available.
429429
pos += 4
@@ -436,7 +436,7 @@ open class ProtoReader(private val source: BufferedSource) {
436436
@Throws(IOException::class)
437437
open fun readFixed64(): Long {
438438
if (state != STATE_FIXED64 && state != STATE_LENGTH_DELIMITED) {
439-
throw ProtocolException("Expected FIXED64 or LENGTH_DELIMITED but was $state")
439+
throw ProtocolException("Expected FIXED64 or LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
440440
}
441441
source.require(8) // Throws EOFException if insufficient bytes are available.
442442
pos += 8
@@ -466,7 +466,7 @@ open class ProtoReader(private val source: BufferedSource) {
466466
@Throws(IOException::class)
467467
private fun beforeLengthDelimitedScalar(): Long {
468468
if (state != STATE_LENGTH_DELIMITED) {
469-
throw ProtocolException("Expected LENGTH_DELIMITED but was $state")
469+
throw ProtocolException("Expected LENGTH_DELIMITED but was $state. Reader position: $pos. Last read tag: $tag.")
470470
}
471471
val byteCount = limit - pos
472472
source.require(byteCount) // Throws EOFException if insufficient bytes are available.

wire-schema/src/jvmTest/kotlin/com/squareup/wire/schema/SchemaProtoAdapterTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ class SchemaProtoAdapterTest {
172172
adapter.decode(Buffer().write(encoded))
173173
fail()
174174
} catch (expected: ProtocolException) {
175-
assertThat(expected).hasMessage("Unexpected end group")
175+
assertThat(expected).hasMessage("Unexpected end group. Reader position: 4. Last read tag: 3.")
176176
}
177177
}
178178

@@ -194,7 +194,7 @@ class SchemaProtoAdapterTest {
194194
adapter.decode(Buffer().write(encoded))
195195
fail()
196196
} catch (expected: ProtocolException) {
197-
assertThat(expected).hasMessage("Unexpected end group")
197+
assertThat(expected).hasMessage("Unexpected end group. Reader position: 5. Last read tag: 3.")
198198
}
199199
}
200200

wire-tests/src/commonTest/kotlin/com/squareup/wire/ParseTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class ParseTest {
5151
OneField.ADAPTER.decode(data.toByteArray())
5252
fail()
5353
} catch (expected: ProtocolException) {
54-
assertThat(expected).hasMessage("Unexpected field encoding: 7")
54+
assertThat(expected).hasMessage("Unexpected field encoding: 7. Reader position: 4. Last read tag: 2.")
5555
}
5656
}
5757

wire-tests/src/jvmJavaTest/java/com/squareup/wire/ParseTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ public void unknownTypeThrowsIOException() throws Exception {
4949
OneField.ADAPTER.decode(data.toByteArray());
5050
fail();
5151
} catch (ProtocolException expected) {
52-
assertThat(expected).hasMessageThat().contains("Unexpected field encoding: 7");
52+
assertThat(expected)
53+
.hasMessageThat()
54+
.contains("Unexpected field encoding: 7. Reader position: 4. Last read tag: 2.");
5355
}
5456
}
5557

0 commit comments

Comments
 (0)