Skip to content

[BUG] Multi-file M4B conversion runs before the destination conflict is detected #284

Description

@bhoffman20

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's Part/PartCount (1 of N), so naming adds a part suffix: Author - Title - 01.m4b. GetConversionDestinationConflictReason checks that path, finds nothing, and conversion starts. The converted file from CreateGeneratedConversionLocalBook (:2375) has no Part/PartCount, so its destination is Author - Title.m4b. If that file already exists, GetAdditionalCopyPathCollisionReason rejects the import after conversion.

To Reproduce

  1. Audiobook quality profile with Convert to Quality = M4B.
  2. Import a multi-file release for a book so it is converted to a single M4B.
  3. Re-import the same release (or another multi-file release of that book).
  4. The full conversion runs, then the import fails: 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 targets Author - 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:

  • OS: Ubuntu
  • Chaptarr Version: develop (0.9.965)
  • Installation Method: built from source

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 GetConvertedImportDestinationPath but keeps the part fields, so a fix here will conflict with it.

Activity

  1. bhoffman20 commented on Oct 4, 2026

    @bhoffman20
    CollaboratorAuthor

    I dont know if this really matters, I'll keep digging

  2. added a commit that references this issue on Oct 5, 2026
    1d0ad03
  3. elric667 commented on Oct 5, 2026

    @elric667

    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. CreateGeneratedConversionLocalBook gives the converted file neither, so the preview now carries the values the import gives that file: Part 1 and no PartCount. As a result:

    • The check before conversion looks at Title.m4b.
    • The output in .chaptarr-conversions gets its final name too. With the default { (PartNumber:smart)} naming it used to be Title (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), with Black Sheep.m4b already 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 is Black Sheep.m4b. Without the fix, it is Black Sheep - 01.m4b.

    The full Chaptarr.Core.Test suite 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: BookFile doesn't store PartCount, 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 develop before #160, let me know. I'll send it as its own PR and rebase #160 onto it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions