[Bug]: audiobookshelf-discord-rpc #2845

Closed
opened 2026-04-25 00:11:15 +02:00 by adam · 2 comments
Owner

Originally created by @WickedWillow13 on GitHub (Jun 15, 2025).

What happened?

When using audiobookshelf-discord-rpc to share current audiobook playback with Discord it causes audiobook to crash. Got this fatal error last occurrence:

[Server] Unhandled rejection: TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) promise: Promise { TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) }

What did you expect to happen?

I did not anticipate this crash to continue to happen. I expected it to continue running along with audiobookslef to share my current listening audio book with discord.

Steps to reproduce the issue

  1. Run and listen to an audio book in audiobookself
  2. Run audiobookshelf-discord-rpc on separate Windows based computer
  3. Wait some time (roughly 1-2 hours) and the audiobookshelf container will crash

Audiobookshelf version

v2.25.1

How are you running audiobookshelf?

Docker

What OS is your Audiobookshelf server hosted from?

Other (list in "Additional Notes" box)

If the issue is being seen in the UI, what browsers are you seeing the problem on?

Chrome

Logs

2025-06-15 00:12:24.480

ERROR

[FantLab] work info request for url "https://api.fantlab.ru/work/38625/extended" error [AxiosError: timeout of 30000ms exceeded] { code: 'ECONNABORTED', config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [Function: httpAdapter], transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 30000, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function] }, validateStatus: [Function: validateStatus], headers: { Accept: 'application/json, text/plain, */*', 'User-Agent': 'axios/0.27.2' }, method: 'get', url: 'https://api.fantlab.ru/work/38625/extended', data: undefined }, request: <ref *1> Writable { _events: { close: undefined, error: [Function: handleRequestError], prefinish: undefined, finish: undefined, drain: undefined, response: [Function: handleResponse], socket: [Array], timeout: undefined, abort: undefined }, _writableState: WritableState { highWaterMark: 16384, length: 0, corked: 0, onwrite: [Function: bound onwrite], writelen: 0, bufferedIndex: 0, pendingcb: 0, [Symbol(kState)]: 17580812, [Symbol(kBufferedValue)]: null }, _maxListeners: undefined, _options: { maxRedirects: 21, maxBodyLength: 10485760, protocol: 'https:', path: '/work/38625/extended', method: 'GET', headers: [Object], agent: undefined, agents: [Object], auth: undefined, hostname: 'api.fantlab.ru', port: null, nativeProtocols: [Object], pathname: '/work/38625/extended' }, _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _eventsCount: 3, _onNativeResponse: [Function (anonymous)], _currentRequest: ClientRequest { _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: true, _last: true, chunkedEncoding: false, shouldKeepAlive: true, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: false, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, _closed: false, socket: [TLSSocket], _header: 'GET /work/38625/extended HTTP/1.1\r\n' + 'Accept: application/json, text/plain, */*\r\n' + 'User-Agent: axios/0.27.2\r\n' + 'Host: api.fantlab.ru\r\n' + 'Connection: keep-alive\r\n' + '\r\n', _keepAliveTimeout: 0, _onPendingData: [Function: nop], agent: [Agent], socketPath: undefined, method: 'GET', maxHeaderSize: undefined, insecureHTTPParser: undefined, joinDuplicateHeaders: undefined, path: '/work/38625/extended', _ended: false, res: null, aborted: true, timeoutCb: [Function: emitRequestTimeout], upgradeOrConnect: false, parser: [HTTPParser], maxHeadersCount: null, reusedSocket: false, host: 'api.fantlab.ru', protocol: 'https:', _redirectable: [Circular *1], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(kBytesWritten)]: 0, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype], [Symbol(errored)]: null, [Symbol(kHighWaterMark)]: 16384, [Symbol(kRejectNonStandardBodyWrites)]: false, [Symbol(kUniqueHeaders)]: null, [Symbol(kError)]: undefined }, _currentUrl: 'https://api.fantlab.ru/work/38625/extended', _timeout: null, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false } }

2025-06-15 00:12:24.619

FATAL

[Server] Unhandled rejection: TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) promise: Promise { <rejected> TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) }

Additional Notes

Audiobook shelf is running as docker container in Unraid.

Image

Originally created by @WickedWillow13 on GitHub (Jun 15, 2025). ### What happened? When using audiobookshelf-discord-rpc to share current audiobook playback with Discord it causes audiobook to crash. Got this fatal error last occurrence: [Server] Unhandled rejection: TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) promise: Promise { <rejected> TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) } ### What did you expect to happen? I did not anticipate this crash to continue to happen. I expected it to continue running along with audiobookslef to share my current listening audio book with discord. ### Steps to reproduce the issue 1. Run and listen to an audio book in audiobookself 2. Run audiobookshelf-discord-rpc on separate Windows based computer 3. Wait some time (roughly 1-2 hours) and the audiobookshelf container will crash ### Audiobookshelf version v2.25.1 ### How are you running audiobookshelf? Docker ### What OS is your Audiobookshelf server hosted from? Other (list in "Additional Notes" box) ### If the issue is being seen in the UI, what browsers are you seeing the problem on? Chrome ### Logs ```shell 2025-06-15 00:12:24.480 ERROR [FantLab] work info request for url "https://api.fantlab.ru/work/38625/extended" error [AxiosError: timeout of 30000ms exceeded] { code: 'ECONNABORTED', config: { transitional: { silentJSONParsing: true, forcedJSONParsing: true, clarifyTimeoutError: false }, adapter: [Function: httpAdapter], transformRequest: [ [Function: transformRequest] ], transformResponse: [ [Function: transformResponse] ], timeout: 30000, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN', maxContentLength: -1, maxBodyLength: -1, env: { FormData: [Function] }, validateStatus: [Function: validateStatus], headers: { Accept: 'application/json, text/plain, */*', 'User-Agent': 'axios/0.27.2' }, method: 'get', url: 'https://api.fantlab.ru/work/38625/extended', data: undefined }, request: <ref *1> Writable { _events: { close: undefined, error: [Function: handleRequestError], prefinish: undefined, finish: undefined, drain: undefined, response: [Function: handleResponse], socket: [Array], timeout: undefined, abort: undefined }, _writableState: WritableState { highWaterMark: 16384, length: 0, corked: 0, onwrite: [Function: bound onwrite], writelen: 0, bufferedIndex: 0, pendingcb: 0, [Symbol(kState)]: 17580812, [Symbol(kBufferedValue)]: null }, _maxListeners: undefined, _options: { maxRedirects: 21, maxBodyLength: 10485760, protocol: 'https:', path: '/work/38625/extended', method: 'GET', headers: [Object], agent: undefined, agents: [Object], auth: undefined, hostname: 'api.fantlab.ru', port: null, nativeProtocols: [Object], pathname: '/work/38625/extended' }, _ended: true, _ending: true, _redirectCount: 0, _redirects: [], _requestBodyLength: 0, _requestBodyBuffers: [], _eventsCount: 3, _onNativeResponse: [Function (anonymous)], _currentRequest: ClientRequest { _events: [Object: null prototype], _eventsCount: 2, _maxListeners: undefined, outputData: [], outputSize: 0, writable: true, destroyed: true, _last: true, chunkedEncoding: false, shouldKeepAlive: true, maxRequestsOnConnectionReached: false, _defaultKeepAlive: true, useChunkedEncodingByDefault: false, sendDate: false, _removedConnection: false, _removedContLen: false, _removedTE: false, strictContentLength: false, _contentLength: 0, _hasBody: true, _trailer: '', finished: true, _headerSent: true, _closed: false, socket: [TLSSocket], _header: 'GET /work/38625/extended HTTP/1.1\r\n' + 'Accept: application/json, text/plain, */*\r\n' + 'User-Agent: axios/0.27.2\r\n' + 'Host: api.fantlab.ru\r\n' + 'Connection: keep-alive\r\n' + '\r\n', _keepAliveTimeout: 0, _onPendingData: [Function: nop], agent: [Agent], socketPath: undefined, method: 'GET', maxHeaderSize: undefined, insecureHTTPParser: undefined, joinDuplicateHeaders: undefined, path: '/work/38625/extended', _ended: false, res: null, aborted: true, timeoutCb: [Function: emitRequestTimeout], upgradeOrConnect: false, parser: [HTTPParser], maxHeadersCount: null, reusedSocket: false, host: 'api.fantlab.ru', protocol: 'https:', _redirectable: [Circular *1], [Symbol(shapeMode)]: false, [Symbol(kCapture)]: false, [Symbol(kBytesWritten)]: 0, [Symbol(kNeedDrain)]: false, [Symbol(corked)]: 0, [Symbol(kOutHeaders)]: [Object: null prototype], [Symbol(errored)]: null, [Symbol(kHighWaterMark)]: 16384, [Symbol(kRejectNonStandardBodyWrites)]: false, [Symbol(kUniqueHeaders)]: null, [Symbol(kError)]: undefined }, _currentUrl: 'https://api.fantlab.ru/work/38625/extended', _timeout: null, [Symbol(shapeMode)]: true, [Symbol(kCapture)]: false } } 2025-06-15 00:12:24.619 FATAL [Server] Unhandled rejection: TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) promise: Promise { <rejected> TypeError: Cannot destructure property 'authors' of 'bookData' as it is null. at FantLab.cleanBookData (/app/server/providers/FantLab.js:96:11) at FantLab.getWork (/app/server/providers/FantLab.js:86:17) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async /app/server/providers/FantLab.js:55:50 at async Promise.all (index 24) at async BookFinder.getFantLabResults (/app/server/finders/BookFinder.js:151:17) at async BookFinder.runSearch (/app/server/finders/BookFinder.js:461:15) at async BookFinder.search (/app/server/finders/BookFinder.js:413:19) at async BookFinder.findCovers (/app/server/finders/BookFinder.js:486:23) at async ApiRouter.findCovers (/app/server/controllers/SearchController.js:58:20) } ``` ### Additional Notes Audiobook shelf is running as docker container in Unraid. ![Image](https://github.com/user-attachments/assets/a8349bc3-2819-4b80-8819-08dd7faedd35)
adam added the bug label 2026-04-25 00:11:15 +02:00
adam closed this issue 2026-04-25 00:11:16 +02:00
Author
Owner

@nichwall commented on GitHub (Jun 15, 2025):

Looks like the issue is here https://github.com/advplyr/audiobookshelf/blob/f3f5f3b9bd540d311a6ab0a99b9317a5142755ea/server/providers/FantLab.js#L95-L117. We can change this to be something like the following (untested and not at a computer to test). This is not checked against their API docs, I am having trouble finding it.

 async cleanBookData(bookData, timeout = this.#responseTimeout) {
   const subtitle = Array.isArray(bookData?.work_name_alts) ? work_name_alts[0] : null
   const authorNames = bookData?.authors?.map((au) => (au.name || '').trim()).filter((au) => au)


   const imageAndIsbn = await this.tryGetCoverFromEditions(bookData?.editions_blocks, timeout)


   const imageToUse = imageAndIsbn?.imageUrl || bookData?.image


   return {
     id: bookData?.work_id,
     title: bookData?.work_name,
     subtitle: subtitle || null,
     author: authorNames.length ? authorNames.join(', ') : null,
     publisher: null,
     publishedYear: bookData?.work_year,
     description: bookData?.work_description,
     cover: imageToUse ? `https://fantlab.ru${imageToUse}` : null,
     genres: this.tryGetGenres(bookData?.classificatory),
     isbn: imageAndIsbn?.isbn || null
   }
 }
@nichwall commented on GitHub (Jun 15, 2025): Looks like the issue is here https://github.com/advplyr/audiobookshelf/blob/f3f5f3b9bd540d311a6ab0a99b9317a5142755ea/server/providers/FantLab.js#L95-L117. We can change this to be something like the following (untested and not at a computer to test). This is not checked against their API docs, I am having trouble finding it. ``` async cleanBookData(bookData, timeout = this.#responseTimeout) { const subtitle = Array.isArray(bookData?.work_name_alts) ? work_name_alts[0] : null const authorNames = bookData?.authors?.map((au) => (au.name || '').trim()).filter((au) => au) const imageAndIsbn = await this.tryGetCoverFromEditions(bookData?.editions_blocks, timeout) const imageToUse = imageAndIsbn?.imageUrl || bookData?.image return { id: bookData?.work_id, title: bookData?.work_name, subtitle: subtitle || null, author: authorNames.length ? authorNames.join(', ') : null, publisher: null, publishedYear: bookData?.work_year, description: bookData?.work_description, cover: imageToUse ? `https://fantlab.ru${imageToUse}` : null, genres: this.tryGetGenres(bookData?.classificatory), isbn: imageAndIsbn?.isbn || null } } ```
Author
Owner

@github-actions[bot] commented on GitHub (Jul 12, 2025):

Fixed in v2.26.0.

@github-actions[bot] commented on GitHub (Jul 12, 2025): Fixed in [v2.26.0](https://github.com/advplyr/audiobookshelf/releases/tag/v2.26.0).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf#2845