From b7ccf2fefa99c73f6b29cbbc4a2375bfc54fd8eb Mon Sep 17 00:00:00 2001 From: Adrian Kuta Date: Wed, 10 Jun 2026 11:57:08 +0200 Subject: [PATCH] fix(core:data): catch deserialization errors in safeCall (review) Deserialization happens in responseToResult via response.body() on the 2xx branch. That call was outside safeCall's try/catch, so a malformed 2xx body threw an uncaught SerializationException (crash) instead of mapping to DataError.Network.SERIALIZATION. Move responseToResult(execute()) inside the try so both transport and parse errors are typed. Found by the milestone review. --- .../core/data/network/HttpClientExt.kt | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/core/data/src/main/kotlin/com/example/architecture/core/data/network/HttpClientExt.kt b/core/data/src/main/kotlin/com/example/architecture/core/data/network/HttpClientExt.kt index b6fa067..edbff16 100644 --- a/core/data/src/main/kotlin/com/example/architecture/core/data/network/HttpClientExt.kt +++ b/core/data/src/main/kotlin/com/example/architecture/core/data/network/HttpClientExt.kt @@ -54,27 +54,30 @@ suspend inline fun HttpClient.delete( } } -/** Wraps a Ktor call, turning transport exceptions into typed [DataError.Network] results. */ +/** + * Wraps a Ktor call AND its response deserialization, turning transport/parse exceptions into typed + * [DataError.Network] results. `responseToResult` runs inside the try so a malformed 2xx body maps + * to SERIALIZATION instead of escaping uncaught. + */ suspend inline fun safeCall( execute: () -> HttpResponse, ): Result { - val response = try { - execute() + return try { + responseToResult(execute()) } catch (e: UnresolvedAddressException) { KermitLogger.withTag("HttpClient").e(e) { "No internet (unresolved address)" } - return Result.Error(DataError.Network.NO_INTERNET) + Result.Error(DataError.Network.NO_INTERNET) } catch (e: UnknownHostException) { KermitLogger.withTag("HttpClient").e(e) { "No internet (unknown host)" } - return Result.Error(DataError.Network.NO_INTERNET) + Result.Error(DataError.Network.NO_INTERNET) } catch (e: SerializationException) { KermitLogger.withTag("HttpClient").e(e) { "Serialization failure" } - return Result.Error(DataError.Network.SERIALIZATION) + Result.Error(DataError.Network.SERIALIZATION) } catch (e: Exception) { if (e is CancellationException) throw e KermitLogger.withTag("HttpClient").e(e) { "Unknown network failure" } - return Result.Error(DataError.Network.UNKNOWN) + Result.Error(DataError.Network.UNKNOWN) } - return responseToResult(response) } /** Maps HTTP status codes to typed [DataError.Network] (extends the skill table with 400/403/404). */