Skip to content

fix: remove phantom offline books on 404#742

Merged
everpcpc merged 3 commits intomainfrom
codex/phantom-book-404-removal
Apr 25, 2026
Merged

fix: remove phantom offline books on 404#742
everpcpc merged 3 commits intomainfrom
codex/phantom-book-404-removal

Conversation

@everpcpc
Copy link
Copy Markdown
Owner

@everpcpc everpcpc commented Apr 25, 2026

Problem

Offline auto-downloads can keep retrying a stale Komga book ID after the server replaces or removes the original file and the old book endpoint starts returning 404. The retry loop needs to be broken without mixing a server-mirrored deleted state with a locally detected orphan.

Approach

Handle confirmed 404 responses by removing the stale local SwiftData book record instead of setting isUnavailable. The removal path also clears offline files, updates Spotlight where supported, refreshes queue status, and re-syncs derived series/read-list download state.

Scope

  • Keep unavailable-book filtering in offline policy selection
  • Replace local tombstoning with local deletion for confirmed book 404s
  • Reuse one offline cleanup path across foreground download, background startup, and background failure callbacks

Validation

  • make format
  • make build

Closes #737
Closes #738

spawvn and others added 3 commits April 25, 2026 20:06
When a Komga book file is replaced, the server issues a new UUID and
the old UUID becomes an orphan. KMReader's policy-driven auto-download
keeps attempting the old UUID, 404s, marks it as .failed, and then
re-enqueues it on the next sweep — producing a stuck failed task that
no in-app action can clear.

Handle the 404 as a permanent "gone" signal instead of a transient
failure:

- Add `markBookUnavailable` to DatabaseOperator. Mirrors the effect of
  a server-delivered `deleted: true` on the book DTO: sets
  isUnavailable = true, resets download state, and re-syncs the series
  so counters are correct.
- Add `isPermanentNotFound` helper to OfflineManager (APIError.notFound
  pattern-match, parallel to isNetworkRelatedError).
- In the three download catch sites (background startup, background
  failure callback, foreground catch), treat 404 as permanent: call
  markBookUnavailable and return before falling through to the .failed
  path.
- Pre-filter isUnavailable books in handlePolicyActions so they neither
  consume a slot in allowedUnreadIds nor get re-enqueued. This is what
  makes the auto-download limit silently promote the next real book
  when the phantom 404s.

Closes the user-visible symptom (stuck phantom in Download Tasks).
The root cause of phantom accumulation — the SSE BookDeleted event
only refreshes the dashboard and doesn't delete the book from
SwiftData — is left as a follow-up for the maintainer.

Refs #737
Handle confirmed book 404s by deleting the stale local SwiftData record instead of mutating the server-mirrored deleted flag. Clean up offline files, refresh derived download status, and keep offline policy filtering for server-deleted books.
@everpcpc everpcpc merged commit c526b04 into main Apr 25, 2026
3 checks passed
@everpcpc everpcpc deleted the codex/phantom-book-404-removal branch April 25, 2026 12:18
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.

Offline download queue stuck on phantom book ID after file rename; only reinstall clears it

2 participants