Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[BUG] Multi-narrator 'Full Cast' naming collapse + tag-dependent IsGraphicAudio detection make regular and dramatized editions path-identical, and upgrade-delete silently removes the other product

Open
#286 2 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 7 days

Nobody has claimed this yet.

Assessment

Difficulty
5/5
Estimated time
Over a week
Newbie friendliness
35/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
csharp, docker
Domain
backend, database

Research direction

Start by reading FileNameBuilder.AddNarratorTokens, DetectGraphicAudioFromLocalTags, and the BookFile API resource and ManualImport handling described in the report. Trace how imports choose destination paths and how upgrade-delete handles a file already at that path. Done means regular and GraphicAudio editions cannot collide or silently delete each other, and the production type can be corrected through the import or API flow.

Written by the indexing model from the issue text.

Description

bug

Describe the bug

Two related behaviors in Chaptarr's organizer and upgrade-delete path combined to permanently destroy files from two different products of the same book. We lost a Golden Son GraphicAudio Part 2 file and a Dark Age GraphicAudio file (permanently — no recycle bin), caused by the sequence below. Both can coexist only if their computed destination paths differ, and in specific cases they don't.

Behavior 1 — narrator-token collapse makes two products path-identical

FileNameBuilder.AddNarratorTokens collapses any edition with more than two narrators to the literal "Full Cast" in the folder name. Books with genuinely multi-narrator regular editions (Iron Gold, Dark Age) therefore compute the same folder/file path as their dramatized (GraphicAudio) counterparts, because both collapse to "Full Cast" and the {Book Title} token is identical. The graphicAudioSuffix is appended only when the BookFile.IsGraphicAudio flag is true — which leads to behavior 2.

Behavior 2 — IsGraphicAudio is not reliably set on import, so the suffix never applies

The flag comes from DetectGraphicAudioFromLocalTags (embedded tags) and title parsing at import time. A GraphicAudio file whose tags don't advertise it (our Dark Age GA m4b, grabbed via SABnzbd) imported with IsGraphicAudio=false, so it computed the same path as the regular edition: Dark Age - Full Cast/Dark Age.m4b. Nothing in the ManualImport payload can set this flag — it's not exposed on the BookFile API resource — so the operator cannot force it at import time.

Combined effect — the actual data loss

When a regular edition was later imported onto the same book (an upgrade in Chaptarr's view), the upgrade-delete path removed the file occupying the computed destination — the GraphicAudio file — and imported the regular file over it. The GA file was permanently deleted (no recycle bin configured). The same collision later struck in reverse during a manual restore: importing the GA file with replaceExistingFiles=true overwrote the regular file at the same computed path. Two products of the same book cannot coexist, and in both directions the loser is silently, permanently deleted.

To Reproduce

  1. Author a book whose regular edition has >2 narrators (e.g. Pierce Brown, Dark Age). Its computed folder is Dark Age - Full Cast/.
  2. Obtain a dramatized/GraphicAudio edition of the same book whose embedded tags do not identify it (or whose import path doesn't detect it). Import it via ManualImport. Its computed destination is also Dark Age - Full Cast/Dark Age.m4b — identical.
  3. Import the regular edition onto the same book with replaceExistingFiles=true. The GA file at the shared path is deleted; the regular file takes its place. No warning that the destination belonged to a different product.

Expected behavior

  • Two products of the same book (regular vs dramatized adaptation) should never compute identical destination paths. Options: include AudioProductionType/IsGraphicAudio in the default naming tokens when set; or treat a destination occupied by a file flagged as a different production type as an occupied-destination conflict (reject/warn) rather than an upgrade to replace.
  • Upgrade-delete should not silently remove a file that is not a prior copy of the same product.
  • IsGraphicAudio / production type should be settable through the BookFile API resource or ManualImport payload, so operators can correct misdetections without SQL.

System Information:

  • OS: Docker on Unraid
  • Chaptarr Version: 0.9.965.0
  • Installation Method: Docker
  • Download clients: NZBGet, qBittorrent, SABnzbd

Logs

Debug-log evidence from the session is available on request (import decision lines, [CLEAN-IMPORT] skips, computed paths both before and after the flag was set via SQL).

Additional context

We recovered both files from out-of-pipeline sources (the original torrent download dir; a re-grab via SABnzbd), set IsGraphicAudio=true via SQL on the BookFile rows, and Chaptarr's own rename then moved them to distinct … - GraphicAudio … folders — confirming the suffix mechanism works and the missing flag was the trigger. The recurring collision, though, is the "Full Cast" collapse plus tag-dependent detection: any multi-narrator regular book with an undetected dramatized counterpart is one upgrade away from silent permanent deletion.


This report was prepared with AI assistance and reviewed by the reporter before filing.

Dominant language
C#
Stars
664
Forks
48
Avg merge
3d 5h
Merged PRs (30d)
1

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Chaptarr/chaptarr

All issues in Chaptarr/chaptarr

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.