diff --git a/internal/audiobooks/abs/libraries_handler.go b/internal/audiobooks/abs/libraries_handler.go index 3e36497c..127921ad 100644 --- a/internal/audiobooks/abs/libraries_handler.go +++ b/internal/audiobooks/abs/libraries_handler.go @@ -571,6 +571,7 @@ func siloItemToLibraryItem(item *models.MediaItem, lib AudiobookLibrary, baseURL Tracks: []AudioTrack{}, Chapters: []ChapterABS{}, NumTracks: 0, // populated by item-detail handler + Tags: []string{}, }, AddedAt: addedAtMs, UpdatedAt: updatedAtMs, diff --git a/internal/audiobooks/abs/types.go b/internal/audiobooks/abs/types.go index f5ee26b3..363a7e20 100644 --- a/internal/audiobooks/abs/types.go +++ b/internal/audiobooks/abs/types.go @@ -121,6 +121,13 @@ type LibraryItemMedia struct { Tracks []AudioTrack `json:"tracks"` Chapters []ChapterABS `json:"chapters"` NumTracks int `json:"numTracks"` + // Tags is a book-level tag list. NEVER null on the wire — the ABS + // Android client's Kotlin `Book.tags: List` is non-nullable, + // so Jackson throws MissingKotlinParameterException when the field + // is absent (or null) and the entire LibraryItem fails to parse — + // which silently breaks downloads (the downloader's apiHandler + // callback receives null and gives up). Always emit [] in v1. + Tags []string `json:"tags"` } // CollapsedSeriesV1 is the per-item annotation real ABS attaches when