retrofit: UndeclaredThrowableException when using "suspend" modifier
Retrofit crashes with UndeclaredThrowableException
when using suspend
modifier and making multiple requests which are supposed to throw IOException
.
Retrofit version: 2.6.0, 2.6.1-SNAPSHOT (20190612)
class RetrofitUndeclaredThrowableExceptionBug {
interface Service {
@GET("/")
suspend fun download()
}
@Test
fun test() = runBlocking {
val retrofit = Retrofit.Builder()
.baseUrl("https://unresolved-host.com/") // An unresolved host to simulate IOException
.build()
val service = retrofit.create<Service>(Service::class.java)
// First attempt works fine
try {
service.download()
} catch (e: IOException) {
println("Catched 1: $e")
}
// Second attempt sometimes crashes
try {
service.download()
} catch (e: IOException) {
println("Catched 2: $e")
}
// And this will crash for sure (sometimes sooner, sometimes later)
repeat(Integer.MAX_VALUE) {
try {
service.download()
} catch (e: IOException) {
println("Catched 3: $e")
}
}
}
}
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 9
- Comments: 17 (10 by maintainers)
The same happens when throwing an exception from an interceptor
There should be a fat warning on the release notes, that using
suspend
modifier for retrofit is not production ready.Network calls can throw checked
IOException
s so you need to declare@Throws(IOException::class)
on every single function on your interface or it will blow up at runtime.I’m still getting the
UndeclaredThrowableExceptions
within my app. Our Retrofit services returnResponses
instead of POJOs. My hunch (that I’m about to try and verify) is that you applied the newyieldAndThrow
logic only toSuspendForBody
but didn’t apply the same logic toSuspendForResponse
, and our services are using the currently unprotectedSuspendForResponse
What’s the difference between a wrapping and a non-wrapping adapter? I’d like to test the difference in exceptions handling.
On Wed, Jul 24, 2019, 02:07 Jake Wharton notifications@github.com wrote: