Skip to content

Fix/komga api improvements#2524

Closed
farfromrefug wants to merge 5 commits intobooklore-app:developfrom
farfromrefug:fix/komga_api_improvements
Closed

Fix/komga api improvements#2524
farfromrefug wants to merge 5 commits intobooklore-app:developfrom
farfromrefug:fix/komga_api_improvements

Conversation

@farfromrefug
Copy link
Copy Markdown
Contributor

🚀 Pull Request

📝 Description

This PR improves the Komga API for use with Mihon/Komikku/Koma/Komelia
That PR has no sideeffect in the rest of booklore

🛠️ Changes Implemented

  • added missing APIs
  • prevent errors while using the APIs from clients
  • improved the clean mode (used only by Koma for now)
  • added "skeleton" APIs not supported by booklore but requested by Komelia

Komelia is not yet fully working because it relies on a complex POST API to request from the db with the condition parameter here https://komga.org/docs/openapi/get-series.
Implementing would be pretty complex. We could directly copy the code from Komga but i am not sure this is something we want

🧪 Testing Strategy

📸 Visual Changes (if applicable)


⚠️ Required Pre-Submission Checklist

Please Read - This Checklist is Mandatory

Important Notice: We've experienced several production bugs recently due to incomplete pre-submission checks. To maintain code quality and prevent issues from reaching production, we're enforcing stricter adherence to this checklist.

All checkboxes below must be completed before requesting review. PRs that haven't completed these requirements will be sent back for completion.

Mandatory Requirements (please check ALL boxes):

  • Code adheres to project style guidelines and conventions
  • Branch synchronized with latest develop branch (please resolve any merge conflicts)
  • 🚨 CRITICAL: Automated unit tests added/updated to cover changes (MANDATORY for ALL Spring Boot backend and Angular frontend changes - this is non-negotiable)
  • 🚨 CRITICAL: All tests pass locally (run ./gradlew test for Spring Boot backend, and ng test for Angular frontend - NO EXCEPTIONS)
  • 🚨 CRITICAL: Manual testing completed in local development environment (verify your changes work AND no existing functionality is broken - test related features thoroughly)
  • Flyway migration versioning follows correct sequence (if database schema was modified)
  • Documentation PR submitted to booklore-docs (required for features or enhancements that introduce user-facing or visual changes)

Why This Matters:

Recent production incidents have been traced back to:

  • Incomplete testing coverage (especially backend)
  • Merge conflicts not resolved before merge
  • Missing documentation for new features

Backend changes without tests will not be accepted. By completing this checklist thoroughly, you're helping maintain the quality and stability of Booklore for all users.

Note to Reviewers: Please verify the checklist is complete before beginning your review. If items are unchecked, kindly ask the contributor to complete them first.


💬 Additional Context (optional)

@acx10
Copy link
Copy Markdown
Collaborator

acx10 commented Jan 30, 2026

@farfromrefug Hi, thanks for the PR! I’m a bit busy right now and don’t have time to test the full flow. Would you be able to coordinate with some testers to confirm that everything works as it should? Thanks.

@acx10 acx10 added the bug Something isn't working label Jan 30, 2026
@farfromrefug
Copy link
Copy Markdown
Contributor Author

@CORAAL @stefanop1 would it be possible fo you guys to test that PR ?

@CORAAL
Copy link
Copy Markdown

CORAAL commented Jan 30, 2026

@CORAAL @stefanop1 would it be possible fo you guys to test that PR ?

Of course, no problem.
I'll get back to you in an hour or two.

@CORAAL
Copy link
Copy Markdown

CORAAL commented Jan 30, 2026

I ran the test on 3 applications:

From Booklore, I enabled OPDS and the Komga API, then configured an OPDS user.
I also increased the upload size limit.

I used four different works: three in CBZ format and one in CBR format.
I will name them: Manga1.cbr, Manga2.cbz, Manga3.cbz, and Webtoon1.cbz.

Each book was stored in a single library.
For each extension, the address used was:
http://10.0.10.23:8080/komga


Connection

  • Koma ✅
  • Komikku ✅
  • Komelia ✅

Note

Each work from the library appears.

  • Metadata (title, author, chapters/volumes, tags) appears if it exists.

Warning

The Komelia application returns an error after about one minute:
SSEClientException: Connect timeout was expired [url=http://10.0.10.23:8080/komga/sse/v1/events, connect_timeout=30000 ms]

  • The error appears regularly but does not prevent using the application or opening a work.
io.ktor.client.plugins.sse.SSEClientException: Connect timeout has expired [url=http://10.0.10.23:8080/komga/sse/v1/events, connect_timeout=30000 ms]
	at androidx.room.TriggerBasedInvalidationTracker$syncTriggers$2$1$1.invokeSuspend(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:313)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:9)
	at kotlinx.coroutines.DispatchedTask.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:107)
	at com.zaxxer.hikari.pool.HikariPool$2.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:11)
	at kotlinx.coroutines.scheduling.TaskImpl.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:3)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:88)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@cf438fc, Dispatchers.Default]
Caused by: io.ktor.client.network.sockets.ConnectTimeoutException: Connect timeout has expired [url=http://10.0.10.23:8080/komga/sse/v1/events, connect_timeout=30000 ms]
	at io.ktor.utils.io.WriterJob.onFailure(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:110)
	at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:177)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1154)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:652)
	at java.lang.Thread.run(Thread.java:1563)
Caused by: java.net.SocketTimeoutException: failed to connect to /10.0.10.23 (port 8080) from /10.0.10.148 (port 33274) after 30000ms
	at libcore.io.IoBridge.connectErrno(IoBridge.java:235)
	at libcore.io.IoBridge.connect(IoBridge.java:179)
	at java.net.PlainSocketImpl.socketConnect(PlainSocketImpl.java:142)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:390)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:230)
	at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:212)
	at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:436)
	at java.net.Socket.connect(Socket.java:646)
	at okhttp3.internal.platform.Platform.connectSocket(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:6)
	at okhttp3.internal.connection.ConnectPlan.connectSocket(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:71)
	at okhttp3.internal.connection.ConnectPlan.connectTcp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:27)
	at okhttp3.internal.connection.FastFallbackExchangeFinder$launchTcpConnect$1.runOnce(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:3)
	at androidx.lifecycle.LiveData$1.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:80)
	... 3 more
	Suppressed: java.net.SocketTimeoutException: failed to connect to /10.0.10.23 (port 8080) from /10.0.10.148 (port 33280) after 30000ms
		... 16 more
	Suppressed: java.net.SocketException: Software caused connection abort
		at java.net.SocketInputStream.socketRead0(Native Method)
		at java.net.SocketInputStream.socketRead(SocketInputStream.java:118)
		at java.net.SocketInputStream.read(SocketInputStream.java:173)
		at java.net.SocketInputStream.read(SocketInputStream.java:143)
		at okio.internal.DefaultSocket$SocketSource.read(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:44)
		at okio.RealBufferedSource.indexOf(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:41)
		at okio.RealBufferedSource.readUtf8LineStrict(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:31)
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:50)
		at androidx.compose.runtime.Latch.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:5)
		at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:232)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.ConnectInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:134)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1726)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:589)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:226)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:90)
		at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:52)
		... 3 more
	Suppressed: java.net.SocketException: Software caused connection abort
		at java.net.SocketOutputStream.socketWrite0(Native Method)
		at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:116)
		at java.net.SocketOutputStream.write(SocketOutputStream.java:156)
		at okio.internal.DefaultSocket$SocketSink.write(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:45)
		at okio.RealBufferedSink.flush(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:17)
		at okhttp3.internal.http1.Http1ExchangeCodec.finishRequest(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:7)
		at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:202)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.ConnectInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:134)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1726)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:589)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:226)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:90)
		at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:52)
		... 3 more
		Suppressed: java.io.IOException: unexpected end of stream on http://10.0.10.23:8080/...
			at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:186)
			at androidx.compose.runtime.Latch.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:5)
			at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:232)
			... 14 more
		Caused by: java.io.EOFException: \n not found: limit=0 content=…
			at okio.RealBufferedSource.readUtf8LineStrict(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:153)
			at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:50)
			... 16 more
	Suppressed: java.net.SocketException: Software caused connection abort
		at java.net.SocketOutputStream.socketWrite0(Native Method)
		at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:116)
		at java.net.SocketOutputStream.write(SocketOutputStream.java:156)
		at okio.internal.DefaultSocket$SocketSink.write(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:45)
		at okio.RealBufferedSink.flush(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:17)
		at okhttp3.internal.http1.Http1ExchangeCodec.finishRequest(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:7)
		at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:202)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.ConnectInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:134)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1726)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:589)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:226)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:90)
		at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:52)
		... 3 more
		Suppressed: java.io.IOException: unexpected end of stream on http://10.0.10.23:8080/...
			at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:186)
			at androidx.compose.runtime.Latch.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:5)
			at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:232)
			... 14 more
		Caused by: java.io.EOFException: \n not found: limit=0 content=…
			at okio.RealBufferedSource.readUtf8LineStrict(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:153)
			at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:50)
			... 16 more
	Suppressed: java.io.IOException: unexpected end of stream on http://10.0.10.23:8080/...
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:186)
		at androidx.compose.runtime.Latch.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:5)
		at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:232)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.ConnectInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:134)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1726)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:589)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:226)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:90)
		at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:52)
		... 3 more
	Caused by: java.io.EOFException: \n not found: limit=0 content=…
		at okio.RealBufferedSource.readUtf8LineStrict(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:153)
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:50)
		... 16 more
	Suppressed: java.io.IOException: unexpected end of stream on http://10.0.10.23:8080/...
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:186)
		at androidx.compose.runtime.Latch.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:5)
		at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:232)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.ConnectInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:134)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1726)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:589)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:226)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:90)
		at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:52)
		... 3 more
	Caused by: java.io.EOFException: \n not found: limit=0 content=…
		at okio.RealBufferedSource.readUtf8LineStrict(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:153)
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:50)
		... 16 more
	Suppressed: java.io.IOException: unexpected end of stream on http://10.0.10.23:8080/...
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:186)
		at androidx.compose.runtime.Latch.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:5)
		at okhttp3.internal.http.CallServerInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:232)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.ConnectInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:134)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1726)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:589)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.cache.CacheInterceptor.intercept(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:226)
		at okhttp3.internal.http.RealInterceptorChain.proceed(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:132)
		at okhttp3.internal.connection.RealCall.getResponseWithInterceptorChain$okhttp(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:90)
		at okhttp3.internal.connection.RealCall$AsyncCall.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:52)
		... 3 more
	Caused by: java.io.EOFException: \n not found: limit=0 content=…
		at okio.RealBufferedSource.readUtf8LineStrict(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:153)
		at okhttp3.internal.http1.Http1ExchangeCodec.readResponseHeaders(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:50)
		... 16 more


Reading

Koma

  • Manga1.cbr: ❌ When opening a volume: No pages found | No error in Docker logs
  • Manga2.cbz: ✅
  • Manga3.cbz: ✅
  • Webtoon1.cbz:❌ When opening a volume: No pages found | No error in Docker logs

Komikku

  • Manga1.cbr: ❌ When opening a volume: No pages found | No error in Docker logs
  • Manga2.cbz: ✅
  • Manga3.cbz: ✅
  • Webtoon1.cbz: ❌ When opening a volume: No pages found | No error in Docker logs

Komelia ❌

  • Manga1.cbr: ❌
    • IndexOutOfBoundsException: Index -1 out of bounds for length 0 See the complete log below (last one)
  • Manga2.cbz: ❌
    • JsonConvertException Illegal input: Fields [sizeBytes, size] are required for type with serial name 'snd.komga.client.book.KomgaBookPage', but they were missing at path: $[0]
  • Manga3.cbz: ❌
    • JsonConvertException Illegal input: Fields [sizeBytes, size] are required for type with serial name 'snd.komga.client.book.KomgaBookPage', but they were missing at path: $[0]
  • Webtoon1.cbz: ❌
    • IndexOutOfBoundsException: Index -1 out of bounds for length 0 See the complete log below (last one)

Komelia with Manga1.cbr and Webtoon1.cbz returns the same error:

java.lang.IndexOutOfBoundsException: Index -1 out of bounds for length 0
	at jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
	at jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
	at jdk.internal.util.Preconditions.checkIndex(Preconditions.java:266)
	at java.util.Objects.checkIndex(Objects.java:391)
	at java.util.ArrayList.get(ArrayList.java:434)
	at snd.komelia.ui.reader.image.paged.PagedReaderState.onNewBookLoaded(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:99)
	at snd.komelia.ui.reader.image.paged.PagedReaderState.access$onNewBookLoaded(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1)
	at snd.komelia.ui.reader.image.paged.PagedReaderState$initialize$4.invokeSuspend(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:16)
	at snd.komelia.ui.reader.image.paged.PagedReaderState$initialize$4.invoke(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:2)
	at snd.komelia.ui.reader.image.paged.PagedReaderState$initialize$4.invoke(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1)
	at kotlinx.coroutines.flow.FlowKt__TransformKt$onEach$$inlined$unsafeTransform$1$2.emit(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:198)
	at kotlinx.coroutines.flow.FlowKt__MergeKt$flattenConcat$1$1.emit(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:1)
	at kotlinx.coroutines.flow.StateFlowImpl.collect(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:173)
	at kotlinx.coroutines.flow.FlowKt__LimitKt$take$$inlined$unsafeFlow$1.collect(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:14)
	at kotlinx.coroutines.flow.FlowKt__LimitKt$dropWhile$$inlined$unsafeFlow$1.collect(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:15)
	at kotlinx.coroutines.flow.FlowKt.collect(Unknown Source:3)
	at io.ktor.client.engine.okhttp.OkHttpEngine$1.invokeSuspend(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:88)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:9)
	at kotlinx.coroutines.DispatchedTask.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:115)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(r8-map-id-a29cd9612d6e895804df616377509a8559a97b922c6ec51da66e3fe3f062faaa:118)
	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@a41751e, Dispatchers.Default]

@farfromrefug
Copy link
Copy Markdown
Contributor Author

@CORAAL awesome tests!
About the sse error in komelia. This is expected in a sense. SSE is for live events from the Komga which we dont support. I open a sse channel (or whatever the name is) to make Komelia not crash, but i guess it is normal for it to timeout.

Also it may appear like Komelia works but if you go into a "series" you won't see the correct books. This is because Komelia use that complex POST API that i did not ported. Not sure it is worth the effort.

About the errors, it is true i only work with CBZ having a ComicInfo.xml. This is an issue with booklore where pageCount is not computed if not part of ComicInfo.xml. Thus it will make all the clients fails. @acx10 any thought about this?

@stefanop1
Copy link
Copy Markdown

@farfromrefug
I'm sorry I can't try out your change. I'd really like to, but I have a tight deadline at work. I'll try to follow up on everything soon.

@beudbeud
Copy link
Copy Markdown

beudbeud commented Mar 9, 2026

need some test?

@farfromrefug
Copy link
Copy Markdown
Contributor Author

@beudbeud not yet. The tricky part is the merging. Too many things have changed in the repo. Getting tricky to follow.
I need to find the time and the will to get into it ;)

…provements

# Conflicts:
#	booklore-api/src/main/java/com/adityachandel/booklore/config/WebMvcConfig.java
#	booklore-api/src/main/java/org/booklore/config/KomgaCleanBeanPropertyWriter.java
#	booklore-api/src/main/java/org/booklore/config/security/SecurityConfig.java
#	booklore-api/src/main/java/org/booklore/controller/KomgaController.java
#	booklore-api/src/main/java/org/booklore/mapper/komga/KomgaMapper.java
#	booklore-api/src/main/java/org/booklore/service/appsettings/AppSettingService.java
#	booklore-api/src/main/java/org/booklore/service/komga/KomgaService.java
#	booklore-api/src/test/java/org/booklore/service/komga/KomgaServiceTest.java
@farfromrefug
Copy link
Copy Markdown
Contributor Author

farfromrefug commented Mar 10, 2026

@acx10 i have updated my PR but i have some issues after that.
Now everytime i do this:

BookEntity book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("Book not found"));
        
        BookMetadataEntity metadata = book.getMetadata();

in KomgaService, metadata is always null. It was working before i merged from develop.
Any idea?

@acx10
Copy link
Copy Markdown
Collaborator

acx10 commented Mar 11, 2026

@acx10 i have updated my PR but i have some issues after that. Now everytime i do this:

BookEntity book = bookRepository.findById(bookId)
                .orElseThrow(() -> new RuntimeException("Book not found"));
        
        BookMetadataEntity metadata = book.getMetadata();

in KomgaService, metadata is always null. It was working before i merged from develop. Any idea?

@farfromrefug Could this be a hibernate issue? Do you see anything suspicious in the backend logs?

@farfromrefug
Copy link
Copy Markdown
Contributor Author

@acx10 no i dont see anything "special" in the logs.
I want to start clean but in the meantime if it is an "update" issue i cant really rollback as i wont be able to reproduce it.
When you say hibernate issue, what do you mean? some cache issue?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants