Repository navigation
[BUG] Multi-file M4B conversion runs before the destination conflict is detected #284
Description
Activity
I dont know if this really matters, I'll keep digging
- added a commit that references this issue
on Oct 5, 2026 Thanks for flagging the overlap with #160. #160 already rewrites
GetConvertedImportDestinationPath, so I've put the fix there to keep the two from colliding. It's the commit "Check the converted file's real destination before converting" on #160.What changed: the destination preview no longer copies the first source file's
Part/PartCount.CreateGeneratedConversionLocalBookgives the converted file neither, so the preview now carries the values the import gives that file:Part1 and noPartCount. As a result:- The check before conversion looks at
Title.m4b. - The output in
.chaptarr-conversionsgets its final name too. With the default{ (PartNumber:smart)}naming it used to beTitle (1).m4b.
One difference from your suggestion: I dropped the part fields for single-file conversions as well. The converted file never has them, whatever the input count. Keeping them for a single file that was one part of a set would bring back the same mismatch.
Tests. There are two new tests in
ImportApprovedBooksAdditionalCopyFixture, and both fail without the change:should_find_a_taken_destination_before_converting_a_multi_part_download: 3 MP3s (parts 1–3 of 3), withBlack Sheep.m4balready on disk. Nothing is converted, and the import is skipped with the conflict reason. Without the fix, the converter runs.should_name_a_merged_multi_part_conversion_without_a_part_suffix: the work-folder output isBlack Sheep.m4b. Without the fix, it isBlack Sheep - 01.m4b.
The full
Chaptarr.Core.Testsuite passes.End to end. I built #160 with and without the change and ran each in Docker. I imported two 3-file MP3 folders for the same book through
DownloadedBooksScan, with the default naming format and Rename on.Second release of a book that already has The Diamond Maker.m4b Without the fix The release is fully converted to .chaptarr-conversions/…/The Diamond Maker (1).m4b, then rejected: "Additional physical copy cannot be imported because the managed destination is already occupied: …/The Diamond Maker.m4b". The M4B is kept in the work folder. With the fix "Conversion skipped because the destination is already occupied: …/The Diamond Maker.m4b". Nothing is converted, and the MP3s are left where they were. Library conversions from #160 go through the same method and get the same fix. In practice they weren't hitting this:
BookFiledoesn't storePartCount, so their preview never had a suffix.On #120: this change merges cleanly with #120 in this method. #120 and #160 already overlap in one other spot, the job-failure return in
ConvertBookGroupIfNeeded, which is unrelated to this fix.If you'd rather land the fix on
developbefore #160, let me know. I'll send it as its own PR and rebase #160 onto it.- The check before conversion looks at
Describe the bug
When a multi-file download is converted to M4B, the destination conflict check before conversion looks at the wrong path. The conversion runs in full, and only then is the import rejected because the real destination is occupied.
GetConvertedImportDestinationPath(ImportApprovedBooks.cs:2415) builds the preview from the first source file'sPart/PartCount(1 of N), so naming adds a part suffix:Author - Title - 01.m4b.GetConversionDestinationConflictReasonchecks that path, finds nothing, and conversion starts. The converted file fromCreateGeneratedConversionLocalBook(:2375) has noPart/PartCount, so its destination isAuthor - Title.m4b. If that file already exists,GetAdditionalCopyPathCollisionReasonrejects the import after conversion.To Reproduce
Additional physical copy cannot be imported because the managed destination is already occupied: .../Author - Title.m4b. The converted file is retained under.chaptarr-conversions.The work-folder output is named
Author - Title - 01.m4b(taken from the checked path), while the import targetsAuthor - Title.m4b.Expected behavior
The conflict is detected before conversion, and nothing is converted.
Suggested fix
Build the preview destination the way the converted file is named: no part number when several files are merged, and the source's part number for a single file.
System Information:
Additional context
Seen while testing #120 (multi-part M4B merge), whose merges go through the same path. The code involved is unchanged on develop, where it also affects multi-file MP3 → M4B conversions (a full re-encode before the rejection). #160 changes
GetConvertedImportDestinationPathbut keeps the part fields, so a fix here will conflict with it.