Skip to content

Load podcast libraries whose podcasts have a free-text release date - #1225

Merged
r0adkll merged 1 commit into
mainfrom
fix/podcast-release-date
Oct 10, 2026
Merged

r0adkll merged 1 commit into
mainfrom
fix/podcast-release-date

Conversation

@r0adkll

@r0adkll r0adkll commented Oct 9, 2026 •

Copy link
Copy Markdown
Owner

Stack

Podcast libraries could fail to load in the Home, Shows and Latest tabs. Audiobookshelf stores a podcast's release date as free text, and Campfire decoded it as an ISO-8601 Instant. The web UI saves "" for podcasts added from an RSS URL, OPML imports save "", and admins can type anything ("2019"). One such podcast throws kotlin.time.InstantFormatException, failing the whole personalized-shelves, library-items or recent-episodes response. Fetch errors with nothing cached are swallowed, so Home keeps the previous library's shelves or spins, and Shows spins with a "--" count.

Closes #1224

What changed

  • PodcastMetadata.releaseDate (data/network/api) is now String?, matching the server's STRING column.
  • NetworkPodcastMetadata.asDomainModel() (PodcastMapping.kt) maps a blank release date to null. The domain model and DB already held it as a String?.
  • PodcastDraft.asCreateMetadata() (PodcastSearchMapping.kt) still sends only an ISO-8601 release date when creating a podcast, now as Instant.toString(). That is the same wire format the Instant serializer produced.
  • New tests:
    • PodcastMetadataTest decodes a podcast item with a blank or non-ISO release date, standalone and inside a personalized podcast shelf.
    • PodcastMappingTest and PodcastSearchMappingTest cover both mapping changes. This adds commonTest source sets to :data:db:mapping and :features:podcasts:impl.

Verification

  • Root cause: on unmodified main, a test decoding a minified podcast item with "releaseDate": "" failed with kotlin.time.InstantFormatException.
  • Writers: confirmed in ABS v2.37.1 that NewModal.vue (web RSS add) and PodcastManager.js (OPML import) write ''.
  • Before/after on the testbed emulator (local ABS, Podcasts library). One podcast was set to releaseDate: "" and another to "2019".
    • main: Home kept showing the audiobook shelves, and Shows and Latest stayed empty. Logcat showed decode failures on /personalized, /items and /recent-episodes (An empty string is not a valid Instant, The input string is too short ... "2019").
    • This branch: Home shows Newest Episodes and Recently Added, including both affected podcasts. Shows lists all 12 podcasts. The "" podcast's detail loads with its episodes. Latest loads, and switching back to Audiobooks works. No decode errors in logcat.
  • Real data: podcast responses from a real 2.37.1 server decode cleanly with these models: library items, personalized shelves, recent episodes, and 8 expanded item details.
  • Checks: ./scripts/ktlint --check, ./gradlew --continue jvmTest test, and compiles for :app:desktop:compileKotlin, :app:android:compileAlphaDebugKotlin and :app:ios:compileKotlinIosSimulatorArm64. All pass.
    • Excluded: :infra:audioplayer:engine-tests:test. Its FFmpeg engine tests can't load the native library on this machine (UnsatisfiedLinkError), and this PR doesn't touch audio code.

Follow-ups

An audit of the other podcast models against ABS v2.37.1 found more fields of the same kind:

  • non-null AudioFile probe fields that ffprobe can leave null;
  • PodcastEpisode.Enclosure.length typed Long?, though the server sends the feed's raw text;
  • maxEpisodesToKeep typed Int?, though the server accepts any number;
  • numEpisodes, which is never decoded, so every podcast from a list or shelf is stored with 0 episodes.

These come next in their own PR.

🤖 Generated with Claude Code

Audiobookshelf stores a podcast's releaseDate as free text: the web UI
saves "" for podcasts added from an RSS URL, OPML imports save "", and
admins can type anything. Decoding it as an Instant failed the whole
personalized-shelves, library-items and recent-episodes responses, so
Home, Shows and Latest never loaded for those libraries.

Decode releaseDate as a String, map a blank value to null, and keep
sending only ISO-8601 dates when creating a podcast.

Closes #1224
@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown
Messages
📖 This PR has been checked by Danger

Generated by 🚫 Danger Kotlin against 8469d71

@github-actions

github-actions Bot commented Oct 9, 2026

Copy link
Copy Markdown

Android APK @ 066b8f8

@r0adkll
r0adkll merged commit cf53383 into main Oct 10, 2026
6 of 7 checks passed
@r0adkll
r0adkll deleted the fix/podcast-release-date branch October 10, 2026 03:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Podcasts don't load in Home and Shows tabs

1 participant