Skip to content

A {SeriesNumber} folder pattern is applied on rename but dropped on import, so Organize can move an imported library #816

Description

@m4bard

A folder naming pattern containing {SeriesNumber} produces one layout when a book arrives by import and a different one when the same book is renamed, so a library can be reorganised by pressing Organize even though no setting has changed.

Same book, same setting, on current canary:

FolderNamingPattern = {Author}/{Series}/{SeriesNumber} - {Title}

import destination      /audiobooks/Arthur Conan Doyle/Sherlock Holmes/The Valley of Fear
rename preview plans    /audiobooks/Arthur Conan Doyle/Sherlock Holmes/7 - The Valley of Fear

The book is Sherlock Holmes #7, so the token has a value. Import drops it, rename keeps it.

As far as I can tell the cause is that the two paths build their token dictionaries separately and do not agree on what is in them. ManualImportPathPlanner has no reference to SeriesNumber anywhere in it. RenameService.Helpers.cs:204 has { "SeriesNumber", audiobook.SeriesNumber ?? string.Empty }.

The reason this is quiet rather than loud is the empty-token handling in FileNamingService. An unrecognised token resolves to the empty sentinel and the separator beside it is then cleaned up, which is the right behaviour for a book with no series, but it means an unsupplied token is indistinguishable from an absent value. So {Author}/{Series}/{SeriesNumber} - {Title} silently becomes {Author}/{Series}/{Title} on import, with nothing in the response or the logs suggesting the pattern was not fully applied.

What I think makes this worth fixing rather than documenting is the consequence rather than the token. A book imported today sits in one folder. Press Organize tomorrow and the rename preview reports a pending change and moves it, and from the outside that looks like Listenarr deciding to reorganise a library on its own. Nothing has changed but which code path last touched the book.

I have not tried to work out which of the two is the intended behaviour, and I do not think that is mine to decide. Whether the series position belongs in a folder name is a product call. The two paths disagreeing about it is the part that looks like a defect.

If it is useful, the check is public and takes one command:

git clone https://github.com/m4bard/listenarr-testdata
cd listenarr-testdata
python3 -m venv .venv && .venv/bin/pip install -e .
./tools/validate_naming_parity.sh --image ghcr.io/listenarrs/listenarr:canary

It puts one book and one pattern through both paths and prints what each produced. --pattern probes a different one, since SeriesNumber is only the token I happened to find; anything supplied by one path and not the other would show up the same way. I did not audit the full token list against both dictionaries, so there may be others.

This is separate from #764 and #795, which are about parsing a series position that is not a plain number. Here the value parses fine and one of the two paths simply never asks for it.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions