audiobookshelf icon indicating copy to clipboard operation
audiobookshelf copied to clipboard

[Bug]: Server crashes

Open digitalwm opened this issue 11 months ago • 1 comments

Describe the issue

FATAL: [Server] Unhandled rejection: TypeError: Cannot read properties of undefined (reading 'authors'), promise: Promise { audiobookshelf | TypeError: Cannot read properties of undefined (reading 'authors') audiobookshelf | at BookScanner.scanNewBookLibraryItem (/server/scanner/BookScanner.js:446:86) audiobookshelf | at process.processTicksAndRejections (node:internal/process/task_queues:95:5) audiobookshelf | at async LibraryItemScanner.scanNewLibraryItem (/server/scanner/LibraryItemScanner.js:178:24) audiobookshelf | at async LibraryScanner.scanFolderUpdates (/server/scanner/LibraryScanner.js:584:30) audiobookshelf | at async LibraryScanner.scanFilesChanged (/server/scanner/LibraryScanner.js:385:33) audiobookshelf | } (Server.js:166)

Steps to reproduce the issue

  1. Matching a book using audible.com

Audiobookshelf version

v2.8.0

How are you running audiobookshelf?

Docker

digitalwm avatar Mar 01 '24 10:03 digitalwm

Looking at the stack trace, the crash seems to have happened not while matching, but while the library watcher was adding a new book (but perhaps both things happened around the same time). The error itself is also very odd.

Can you please attach the full log file so I can examine what led up to the crash? you can find it under <your_metadata_dir>/logs/daily

mikiher avatar Mar 01 '24 20:03 mikiher

2024-03-01.txt

digitalwm avatar Mar 03 '24 15:03 digitalwm

Thanks. In your server settings, Do you have "Store covers with item" enabled?

mikiher avatar Mar 08 '24 08:03 mikiher

Yes I do.

digitalwm avatar Mar 08 '24 09:03 digitalwm

OK, then I believe I understand the root cause for this crash.

TLDR: This is caused by a race condition accessing Database.libraryFilterData[libraryId]. This race condition happens because the Store covers with item setting is enabled.

Analysis: Store covers with item enabled means that when submitting a match result with a new cover, the cover is downloaded to the book's library directory, rather than then to the book's metadata directory. Now two things happen in parallel:

  1. The new cover in the book's library directory triggers the library watcher, which checks if it needs to do something with that file.
  2. Book metadata changes due to the submitted match are updated in the book's record.

The two code paths above might be running interleaved due to their asynchronous nature.

Specifically, within path 1, the following happens: 1.a. Database.libraryFilterData[libraryId] is populated here 1.b Database.libraryFilterData[libraryId] is accessed here (where the crash happens).

and within code path 2, the following happens: 2.a. Database.libraryFilterData[libraryId] is deleted (since it's invalid and needs to be reread) here

Now, since the code between 1.a and 1.b is highly asynchronous, the code may run in the following sequence:

  • 1.a
  • 2.a
  • 1.b

This will cause the crash we see at 1.b, since Database.libraryFilterData[libraryId] is deleted at that point.

Solution: Database.libraryFilterData[libraryId] needs to be checked for validity right before every access.

I will work on a fix.

As a workaround until this is fixed, you can disable the Store covers with item setting, or disable the library watcher.

mikiher avatar Mar 08 '24 17:03 mikiher

Hi, thank you for your detailed response and workaround. Also thank you in advance for the fix.

digitalwm avatar Mar 08 '24 17:03 digitalwm

Fixed in v2.8.1

advplyr avatar Mar 16 '24 23:03 advplyr

Thank you again for fixing this. Much appreciated.

digitalwm avatar Mar 18 '24 08:03 digitalwm