BookLore icon indicating copy to clipboard operation
BookLore copied to clipboard

Missing Book Cover For Every Book

Open iamronr opened this issue 6 months ago • 15 comments

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.

Image

Image

These books were stored in my iCloud Drive prior to moving them to an external drive. Any idea what may be causing this?

iamronr avatar May 15 '25 19:05 iamronr

If I delete the actual books, those covers still remain... I've since restored them though.

Image

iamronr avatar May 15 '25 19:05 iamronr

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.

Image

Image

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!

adityachandelgit avatar May 15 '25 19:05 adityachandelgit

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...

iamronr avatar May 15 '25 19:05 iamronr

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.

Image

Image

iamronr avatar May 15 '25 19:05 iamronr

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.

iamronr avatar May 15 '25 19:05 iamronr

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...

iamronr avatar May 15 '25 19:05 iamronr

It also seems to trigger if I do a rescan of the library to bring in a book:

Image

I hope this helps

iamronr avatar May 15 '25 19:05 iamronr

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!

iamronr avatar May 15 '25 19:05 iamronr

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.

adityachandelgit avatar May 17 '25 05:05 adityachandelgit

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 ..

iamronr avatar May 17 '25 19:05 iamronr

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/.*

PrathikGopal avatar May 18 '25 19:05 PrathikGopal

I wish I could say it worked, but it's not for right now. It's not seeing any files starting with . unfortunately.

iamronr avatar May 19 '25 02:05 iamronr

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.

afairgiant avatar May 26 '25 15:05 afairgiant

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.

iamronr avatar May 30 '25 14:05 iamronr

So as long as booklore is picking up the main .epub and ignoring the ._foo.epub files we should be good yes?

afairgiant avatar May 31 '25 22:05 afairgiant