BookLore
BookLore copied to clipboard
Missing Book Cover For Every Book
I have a weird graphical bug. I'm not sure how to fixed it as I don't see where these said book covers are when I check the directory it's in, even with "show hidden files" toggled on.
These books were stored in my iCloud Drive prior to moving them to an external drive. Any idea what may be causing this?
If I delete the actual books, those covers still remain... I've since restored them though.
I have a weird graphical bug. I'm not sure how to fixed it as I don't see where these said book covers are when I check the directory it's in, even with "show hidden files" toggled on.
These books were stored in my iCloud Drive prior to moving them to an external drive. Any idea what may be causing this?
This issue is likely related to files or folders starting with a dot (.), which are typically hidden by default on most systems. Since the books were previously stored in iCloud Drive, it’s possible some metadata or hidden files carried over during the move.
I’ll try to reproduce the issue and work on a fix. Appreciate you flagging it!
My pleasure. This looks amazing btw! And yes, you'd think they're hidden since there's a . in front of the file, but I don't see them even with me being able to see the hidden files. I can see the .env where my docker-compose is, but when I navigate to the folder where these books are stored, I don't see those files.
I may try to import a book manually. I think I just copied and pasted the "Books" directory from my iCloud Drive. I'll troubleshoot further on my end as well...
I can confirm it's definitely because it was a book in iCloud Drive. I grabbed another book and moved it from the Downloads folder into the directory where my books are stored, and it loaded fine. Copied one from iCloud Drive and it added that extra book with a missing cover.
Another discovery... if I log into iCloud.com and access iCloud Drive, download the book from there, and import it, it imports fine without the missing cover. So it's definitely an iCloud Drive issue, when accessing from the Desktop, which in my case is MacOS.
I stand corrected unfortunately. It appears it happens when Importing a bunch of books at a time. One by one it imports fine, but if I'm adding a folder full of books, it creates those missing cover titles as well...
I reimported using just the two books I downloaded instead of copying from iCloud Drive. I copied a book from iCloud Drive, just one, and it imported fine as well...
So the bug appears to be when a folder full of books is imported, is when it happens...
It also seems to trigger if I do a rescan of the library to bring in a book:
I hope this helps
2025-05-15T19:45:20.413Z INFO 1 --- [booklore-api] [ virtual-844] c.a.b.service.LibraryProcessingService : Processing file: Barack Obama - A Promised Land-Random House Digital (2020).epub
2025-05-15T19:45:21.395Z INFO 1 --- [booklore-api] [ virtual-844] c.a.b.service.LibraryProcessingService : Processed file: Barack Obama - A Promised Land-Random House Digital (2020).epub
2025-05-15T19:45:21.396Z INFO 1 --- [booklore-api] [ virtual-844] c.a.b.service.LibraryProcessingService : Processing file: ._Barack Obama - A Promised Land-Random House Digital (2020).epub
2025-05-15 19:45:21.402 [D] io.documentnode.epub4j.epub.EpubReader - Cannot invoke "io.documentnode.epub4j.domain.Resource.getHref()" because "packageResource" is null
java.lang.NullPointerException: Cannot invoke "io.documentnode.epub4j.domain.Resource.getHref()" because "packageResource" is null
at io.documentnode.epub4j.epub.PackageDocumentReader.read(PackageDocumentReader.java:51)
at io.documentnode.epub4j.epub.EpubReader.processPackageResource(EpubReader.java:132)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:107)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:98)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:74)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:54)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:34)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.setBookMetadata(EpubProcessor.java:99)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.processNewFile(EpubProcessor.java:67)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.lambda$processFile$0(EpubProcessor.java:58)
at java.base/java.util.Optional.orElseGet(Unknown Source)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.processFile(EpubProcessor.java:58)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:380)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:727)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor$$SpringCGLIB$$0.processFile(<generated>)
at com.adityachandel.booklore.service.LibraryProcessingService.processLibraryFile(LibraryProcessingService.java:139)
at com.adityachandel.booklore.service.LibraryProcessingService.processLibraryFiles(LibraryProcessingService.java:125)
at com.adityachandel.booklore.service.LibraryProcessingService.rescanLibrary(LibraryProcessingService.java:106)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:380)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:727)
at com.adityachandel.booklore.service.LibraryProcessingService$$SpringCGLIB$$0.rescanLibrary(<generated>)
at com.adityachandel.booklore.service.LibraryService.lambda$rescanLibrary$9(LibraryService.java:182)
at java.base/java.lang.VirtualThread.run(Unknown Source)
2025-05-15 19:45:21.403 [D] io.documentnode.epub4j.epub.NCXDocument - Book does not contain a table of contents file
2025-05-15 19:45:21.403 [D] io.documentnode.epub4j.epub.EpubReader - Cannot invoke "io.documentnode.epub4j.domain.Resource.getHref()" because "packageResource" is null
java.lang.NullPointerException: Cannot invoke "io.documentnode.epub4j.domain.Resource.getHref()" because "packageResource" is null
at io.documentnode.epub4j.epub.PackageDocumentReader.read(PackageDocumentReader.java:51)
at io.documentnode.epub4j.epub.EpubReader.processPackageResource(EpubReader.java:132)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:107)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:98)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:74)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:54)
at io.documentnode.epub4j.epub.EpubReader.readEpub(EpubReader.java:34)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.generateCover(EpubProcessor.java:79)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.processNewFile(EpubProcessor.java:68)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.lambda$processFile$0(EpubProcessor.java:58)
at java.base/java.util.Optional.orElseGet(Unknown Source)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor.processFile(EpubProcessor.java:58)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:380)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:727)
at com.adityachandel.booklore.service.fileprocessor.EpubProcessor$$SpringCGLIB$$0.processFile(<generated>)
at com.adityachandel.booklore.service.LibraryProcessingService.processLibraryFile(LibraryProcessingService.java:139)
at com.adityachandel.booklore.service.LibraryProcessingService.processLibraryFiles(LibraryProcessingService.java:125)
at com.adityachandel.booklore.service.LibraryProcessingService.rescanLibrary(LibraryProcessingService.java:106)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:380)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:727)
at com.adityachandel.booklore.service.LibraryProcessingService$$SpringCGLIB$$0.rescanLibrary(<generated>)
at com.adityachandel.booklore.service.LibraryService.lambda$rescanLibrary$9(LibraryService.java:182)
at java.base/java.lang.VirtualThread.run(Unknown Source)
2025-05-15 19:45:21.403 [D] io.documentnode.epub4j.epub.NCXDocument - Book does not contain a table of contents file
2025-05-15T19:45:21.403Z ERROR 1 --- [booklore-api] [ virtual-844] c.a.b.s.fileprocessor.EpubProcessor : Error generating cover for epub file ._Barack Obama - A Promised Land-Random House Digital (2020).epub, error: Cannot invoke "io.documentnode.epub4j.domain.Resource.getData()" because "coverImage" is null
2025-05-15T19:45:21.408Z INFO 1 --- [booklore-api] [ virtual-844] c.a.b.service.LibraryProcessingService : Processed file: ._Barack Obama - A Promised Land-Random House Digital (2020).epub
2025-05-15T19:45:21.411Z WARN 1 --- [booklore-api] [ virtual-844] c.a.booklore.service.LibraryService : InvalidDataAccessApiUsageException - Library id: 4
2025-05-15T19:45:21.411Z INFO 1 --- [booklore-api] [ virtual-844] c.a.booklore.service.LibraryService : Parsing task completed!
Sure! Could you check if the files starting with a dot are actual EPUB files? In the next release, I plan to filter those out during scanning.
Sure! Could you check if the files starting with a dot are actual EPUB files? In the next release, I plan to filter those out during scanning.
Yep I’ve checked. That was the first thing I checked before I reported it. I definitely didn’t want to waste your time if it was.
If you can I recommend making it a toggle in case there are users that have books that start with a ..
I see the dot filename created for each pdf and epub while copying into the books folder. Below command clears the . files for now.
sudo rm -rf /books/.*
I wish I could say it worked, but it's not for right now. It's not seeing any files starting with . unfortunately.
I did some searching and it seems like underneath the hood, macOS/iCloud is depositing hidden AppleDouble files (names prefixed with ._) alongside each real .epub. source When BookLore’s scanner does a bulk import or rescan, it picks up both the real Foo.epub and the hidden ._Foo.epub, tries to process each as a book, and the “dot‐file” version has no valid ePub content—so no cover, plus an NPE in the logs:
2025-05-15 19:45:21.403 [D] io.documentnode.epub4j.epub.NCXDocument - Book does not contain a table of contents file
2025-05-15T19:45:21.403Z ERROR 1 --- [booklore-api] [ virtual-844] c.a.b.s.fileprocessor.EpubProcessor : Error generating cover for epub file ._Barack Obama - A Promised Land-Random House Digital (2020).epub, error: Cannot invoke "io.documentnode.epub4j.domain.Resource.getData()" because "coverImage" is null
2025-05-15T19:45:21.408Z INFO 1 --- [booklore-api] [ virtual-844] c.a.b.service.LibraryProcessingService : Processed file: ._Barack Obama - A Promised Land-Random House Digital (2020).epub
2025-05-15T19:45:21.411Z WARN 1 --- [booklore-api] [ virtual-844] c.a.booklore.service.LibraryService : InvalidDataAccessApiUsageException - Library id: 4
2025-05-15T19:45:21.411Z INFO 1 --- [booklore-api] [ virtual-844] c.a.booklore.service.LibraryService : Parsing task completed!
But when you do the single upload it works becuase you are only doing the original epub file.
I did some searching and it seems like underneath the hood, macOS/iCloud is depositing hidden AppleDouble files (names prefixed with ._) alongside each real .epub. source When BookLore’s scanner does a bulk import or rescan, it picks up both the real Foo.epub and the hidden ._Foo.epub, tries to process each as a book, and the “dot‐file” version has no valid ePub content—so no cover, plus an NPE in the logs:
2025-05-15 19:45:21.403 [D] io.documentnode.epub4j.epub.NCXDocument - Book does not contain a table of contents file 2025-05-15T19:45:21.403Z ERROR 1 --- [booklore-api] [ virtual-844] c.a.b.s.fileprocessor.EpubProcessor : Error generating cover for epub file ._Barack Obama - A Promised Land-Random House Digital (2020).epub, error: Cannot invoke "io.documentnode.epub4j.domain.Resource.getData()" because "coverImage" is null 2025-05-15T19:45:21.408Z INFO 1 --- [booklore-api] [ virtual-844] c.a.b.service.LibraryProcessingService : Processed file: ._Barack Obama - A Promised Land-Random House Digital (2020).epub 2025-05-15T19:45:21.411Z WARN 1 --- [booklore-api] [ virtual-844] c.a.booklore.service.LibraryService : InvalidDataAccessApiUsageException - Library id: 4 2025-05-15T19:45:21.411Z INFO 1 --- [booklore-api] [ virtual-844] c.a.booklore.service.LibraryService : Parsing task completed!But when you do the single upload it works becuase you are only doing the original epub file.
I had a feeling it was something like that. I’m not sure what Apple is looking to achieve by doing that. Seems pointless unless it’s a Spotlight thing.
So as long as booklore is picking up the main .epub and ignoring the ._foo.epub files we should be good yes?