From 02da884f176e51c9ced8a95fa0954b4906522de7 Mon Sep 17 00:00:00 2001 From: Constantin Piber <59023762+cpiber@users.noreply.github.com> Date: Sun, 11 Jan 2026 22:48:16 +0100 Subject: [PATCH] fix: Do not return inputStream from conversion & handle conversion error (#1854) * fix: Do not return `inputStream` from conversion The returned value must be owned, since the caller closes the input stream on success * fix: Assume a conversion error consumes the input stream e.g. converting an ARGB png to jpeg will throw "bogus colorspace", but only after the inputstream is consumed. so in case of an exception, we have to assume that the stream is broken and re-open the page from cache --- .../kotlin/suwayomi/tachidesk/manga/impl/Page.kt | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt index 9e0f80f7..cf7915e3 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Page.kt @@ -169,7 +169,9 @@ object Page { ) } catch (e: Exception) { logger.error(e) { "Error while post-processing image" } - null + // re-open cached image in case of an error, since conversion likely (partially) consumed the input stream + // so it's likely not possible to serve it + getPageImage(mangaId = mangaId, chapterIndex = chapterIndex, index = index) } return converted?.also { inputStream.close() } ?: (inputStream to mime) } @@ -269,11 +271,12 @@ object Page { return processedStream to mime } + throw Exception("HTTP-service did not return a usable stream") } catch (e: Exception) { // HTTP post-processing failed, continue with original image logger.warn(e) { "Error while post-processing image" } + throw e } - return null } else { if (mime == conversion.target) { return null @@ -296,7 +299,7 @@ object Page { ) if (conversionWriter == null) { logger.warn { "Conversion aborted: No reader for target format ${target.target}" } - return inputStream to sourceMimeType + return null } val (writer, writerParams) = conversionWriter @@ -310,13 +313,13 @@ object Page { writer.write(null, IIOImage(inImage, null, null), writerParams) } } catch (e: Exception) { - logger.warn(e) { "Conversion aborted" } - return null + logger.warn(e) { "Conversion aborted ($sourceMimeType -> ${target.target})" } + throw e } finally { writer.dispose() } val inStream = ByteArrayInputStream(outStream.toByteArray()) - return Pair(inStream.buffered(), target.target) + return inStream.buffered() to target.target } private fun getConversionWriter(