Repository navigation
Conversation
File tags are not a trusted source of identifiers. Calibre writes its internal UUID into the MOBI/AZW3 EXTH ASIN record (113), so a converted file carries a value such as "a2f97540-d315-4ee6-a025-5325c852d261" in the field the importer reads as an ASIN. BookDistance compared that UUID against the edition ASIN and counted it as a mismatch, which is weighted at 10.0 against the book title's 3.0. An edition that has an ASIN was therefore penalised far more heavily than a wrong-title edition with no ASIN at all (weight 0.1), so a different book by the same author could win the match. Validate the local identifier against the expected format before using it and ignore it otherwise, so a malformed value behaves the same as a missing one. Signed-off-by: Amir Zarrinkafsh <3339418+nightah@users.noreply.github.com>
… mismatch A matching identifier is strong evidence that an edition is the right one, but a differing identifier is not evidence that it is the wrong book. Editions of the same work legitimately carry different ISBNs and ASINs, and the metadata source frequently holds an identifier the file does not. Scoring a mismatch at weight 10.0 meant the correct book scored worse than an unrelated book by the same author that simply had no identifier to compare (weight 0.1), because a wrong title only costs 3.0. Observed with a Calibre converted file whose valid ASIN did not appear on the correct book's editions: [Twisted Lies] title exact, asin differs -> 0.3855 [Twisted Games] title differs, no asin -> 0.0644 (chosen) Reward a match instead of punishing a mismatch, so an identifier can promote the right edition but can no longer select a different book. Signed-off-by: Amir Zarrinkafsh <3339418+nightah@users.noreply.github.com>
…lder UpgradeBookFile deleted every BookFile attached to the book being imported, identified only by the path stored in the database. When a file has been matched to the wrong book - which the metadata distance calculation can do for files carrying an unusable identifier - importing the real file for that book deletes the unrelated one: bookFileImported bookId=3 | Ana Huang - Twisted Games bookFileDeleted bookId=3 | /books/Ana Huang/Twisted Lies/Twisted Lies.azw3 | reason=Upgrade With no Recycle Bin configured, RecycleBinProvider deletes permanently, so the unrelated book is gone. Reported in pennydreadful#173. Work out where the incoming file will land and only replace existing files in that folder. Anything else is not a copy of this book being upgraded, so leave it on disk, detach it from the book and warn; the next scan picks it up as an unmapped file. If the destination cannot be calculated the previous behaviour is kept, so imports are never blocked by this check. Calibre libraries are unaffected: files there are addressed by CalibreId. Signed-off-by: Amir Zarrinkafsh <3339418+nightah@users.noreply.github.com>
…lders
A tracked download adopted from the download client's history has no import
item, so the post-import cleanup threw and the whole ManualImport command was
reported as failed even though every file had already been imported:
System.NullReferenceException: Object reference not set to an instance of an object.
at NzbDrone.Core.MediaFiles.BookImport.Manual.ManualImportService.Execute(ManualImportCommand message)
Skip the folder cleanup when there is no import item; there is no output
folder to remove in that case.
Signed-off-by: Amir Zarrinkafsh <3339418+nightah@users.noreply.github.com>
pennydreadful
enabled auto-merge (squash)
September 22, 2026 13:10
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Database Migration
NO
Description
Fixes a data-loss path: importing a book can permanently delete an unrelated book's file. Reported in #173, reproduced here with debug/trace logs, and fixed in four independent commits (each stands alone, split them if you prefer).
What happens. A file whose tags carry an unusable identifier is matched to the wrong book, and the next import for that book deletes it as an "upgrade":
With no Recycle Bin configured
RecycleBinProviderdeletes permanently, which is the loss reported in #173.Why the file was mis-matched. Calibre writes its internal UUID into the MOBI/AZW3 EXTH ASIN record (113).
DistanceCalculatorreads it as an ASIN and compares it to the edition ASIN at weight 10.0, while a wrong title costs only 3.0 and a missing identifier 0.1. The correct book therefore scores worse than a different book by the same author that has no ASIN at all:8 of 24 Kindle-format files in the library I reproduced this on carry such a UUID, produced by five different Calibre versions, so this is not a one-off.
Commits
fix(identification): ignore malformed ASIN/ISBN values from file tags- validate the identifier from file tags before using it; a malformed value is treated like a missing one.fix(identification): treat a differing ISBN/ASIN as unknown, not as a mismatch- editions of the same work legitimately carry different identifiers, and the metadata source often holds one the file does not. Reward a match rather than punish a mismatch, so an identifier can promote the right edition but can no longer select a different book.fix(import): never delete an existing file outside the destination folder- the actual data-loss guard.UpgradeBookFiledeleted everyBookFilerow attached to the book, wherever it lived. Now only files in the folder the incoming file will occupy are replaced; anything else is left on disk, detached from the book and warned about, and the next scan picks it up as an unmapped file. If the destination cannot be calculated the old behaviour is kept, so imports are never blocked. Calibre libraries are unaffected.fix(manualimport): guard null ImportItem when cleaning up download folders-ManualImportthrew aNullReferenceExceptionafter importing successfully when the tracked download came from the client's history rather than a grab.Todos
Notes for reviewers
replaceExistingFilesis dead. The flag is plumbed from the manual import API throughImportApprovedBooksbut its only consumer,RemoveExistingTrackFiles, is commented out atImportApprovedBooks.cs:128-131. Passingfalsedoes not prevent existing files from being deleted. Not touched here - it deserves its own decision: implement it or remove it from the API.Issues Fixed or Closed by this PR