You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Version: v2.3.1 (also present on develop as of today)
Summary
CbxReaderService selects the unpacker purely from the file extension, even though BookLore already detects the real archive type from magic bytes at scan time and stores it in book_file.archive_type. Any comic whose extension disagrees with its content is therefore unreadable, while the library UI shows it as a perfectly normal book.
In my library this affects 3,982 of 22,772 books — ZIP archives distributed as .cbr are extremely common in comic torrents/scan packs, and a few 7-Zip ones too.
streamEntryFromArchive(...) a few lines below dispatches the same way.
So a ZIP named *.cbr goes to getImageEntriesFromRar → junrar throws → the unrar CLI fallback also fails (it is not a RAR) → IOException → ApiError.FILE_READ_ERROR. Same for a RAR named *.cbz.
Meanwhile ArchiveUtils.detectArchiveType(File) already does exactly the right thing (ZIP/RAR/7z magic, extension only as a last-resort fallback), and its result is persisted — book_file.archive_type in my DB is ZIP for every one of those .cbr files. The reader just never looks at it.
Reproduce
Take any CBZ, rename it to .cbr, put it in a library, scan.
The book appears normally; book_file.archive_type is correctly ZIP.
Open it in the web reader, or call GET /api/v1/cbx/{id}/pages — read error.
Through the Komga-compatible API the failure is quieter: pages are listed (that list comes from book_metadata.page_count), but every /komga/api/v1/books/{id}/pages/{n} returns nothing usable, so clients like Mihon show a blank chapter.
Suggested fix
Dispatch on the detected type rather than the name, e.g. in scanArchiveMetadata / streamEntryFromArchive:
detectArchiveType already falls back to the extension when the magic bytes are unreadable, so this is strictly more permissive than the current behaviour and needs no migration — archive_type is stored per file but re-detecting is one 8-byte read and the result is cached alongside the entry list anyway.
Workaround for anyone hitting this now
Rename the files so the extension matches the content (ZIP → .cbz, RAR → .cbr, 7z → .cb7) and update book_file.file_name in the same transaction so BookLore keeps pointing at the existing rows. The library watcher handles it gracefully on its own too: handleFileDelete parks the row in PendingDeletionPool for 8 s and handleNewBookFile matches it back by hash via recoverBook, so read progress survives.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Version: v2.3.1 (also present on
developas of today)Summary
CbxReaderServiceselects the unpacker purely from the file extension, even though BookLore already detects the real archive type from magic bytes at scan time and stores it inbook_file.archive_type. Any comic whose extension disagrees with its content is therefore unreadable, while the library UI shows it as a perfectly normal book.In my library this affects 3,982 of 22,772 books — ZIP archives distributed as
.cbrare extremely common in comic torrents/scan packs, and a few 7-Zip ones too.Where
booklore-api/src/main/java/org/booklore/service/reader/CbxReaderService.javastreamEntryFromArchive(...)a few lines below dispatches the same way.So a ZIP named
*.cbrgoes togetImageEntriesFromRar→ junrar throws → theunrarCLI fallback also fails (it is not a RAR) →IOException→ApiError.FILE_READ_ERROR. Same for a RAR named*.cbz.Meanwhile
ArchiveUtils.detectArchiveType(File)already does exactly the right thing (ZIP/RAR/7z magic, extension only as a last-resort fallback), and its result is persisted —book_file.archive_typein my DB isZIPfor every one of those.cbrfiles. The reader just never looks at it.Reproduce
.cbr, put it in a library, scan.book_file.archive_typeis correctlyZIP.GET /api/v1/cbx/{id}/pages— read error.book_metadata.page_count), but every/komga/api/v1/books/{id}/pages/{n}returns nothing usable, so clients like Mihon show a blank chapter.Suggested fix
Dispatch on the detected type rather than the name, e.g. in
scanArchiveMetadata/streamEntryFromArchive:detectArchiveTypealready falls back to the extension when the magic bytes are unreadable, so this is strictly more permissive than the current behaviour and needs no migration —archive_typeis stored per file but re-detecting is one 8-byte read and the result is cached alongside the entry list anyway.Workaround for anyone hitting this now
Rename the files so the extension matches the content (
ZIP → .cbz,RAR → .cbr,7z → .cb7) and updatebook_file.file_namein the same transaction so BookLore keeps pointing at the existing rows. The library watcher handles it gracefully on its own too:handleFileDeleteparks the row inPendingDeletionPoolfor 8 s andhandleNewBookFilematches it back by hash viarecoverBook, so read progress survives.All reactions