Describe the bug
{Book SeriesPosition} in ebook naming patterns (ebookStandardBookFormat) ignores any :customFormat suffix, so zero-padding like {Book SeriesPosition:00} silently has no effect. This makes it impossible to match the padded series-index convention several other library tools use (e.g. Kavita/Calibre-style 01 - Title), so multi-book series import with inconsistent, non-zero-padded folder names (1 - Title, 2 - Title, ... 10 - Title), which sorts wrong lexicographically.
The generic :customFormat capture already exists in FileNameBuilder.TitleRegex and is honored by {PartNumber}/{PartCount} via FormatPartToken() (value.ToString(customFormat), with a smart mode that pads to the width of the sibling PartCount). But the {Book SeriesPosition} handler in AddBookTokens never reads TokenMatch.CustomFormat at all:
// src/NzbDrone.Core/Organizer/FileNameBuilder.cs, AddBookTokens
tokenHandlers["{Book SeriesPosition}"] = m =>
seriesPosition ?? m.DefaultValue("");
I'd guess this is because Book.SeriesPosition is a string (to allow values like "2.5" for novellas), so it can't just reuse int.ToString(customFormat) the way PartNumber does — it needs to parse the numeric part first and pad only that, while still passing non-numeric/fractional values through unpadded (or pad only the integer part, e.g. 02.5).
To Reproduce
- Settings → Metadata Profiles/Naming (or the
naming/examples API) → set ebookStandardBookFormat to include {Book SeriesPosition:00 - }{Book Title}.
- Import or preview a book at series position
1.
- Rendered folder/file name is
1 - Title, not 01 - Title.
Verified via the naming preview API directly:
GET /api/v1/config/naming/examples?...&standardBookFormat={Book%20Series}/{Book%20SeriesPosition:00%20-%20}{Book%20Title}
→ "singleBookExample": "Series Title/1 - The Edition Title"
(:0, :00, and made-up suffixes all render identically to no suffix — confirms the token handler discards CustomFormat entirely rather than rejecting an invalid format.)
Expected behavior
{Book SeriesPosition:00} should zero-pad the integer part of the series position to at least 2 digits (1 → 01, 10 → 10, 2.5 → 02.5), mirroring how {PartNumber:00} / {PartNumber:smart} behave.
System Information
- Chaptarr Version: 0.9.929 (also reproduced by reading
FileNameBuilder.cs at current develop HEAD)
- Installation Method: Docker
Additional context
Happy to send a PR — the fix looks like a small, self-contained addition to AddBookTokens that parses the leading integer from seriesPosition, applies int.ToString(customFormat) (or a smart mode) to it, and reattaches any fractional/non-numeric remainder, falling back to the raw string when it isn't a recognizable number. Let me know if that approach sounds right before I put up a PR.
Describe the bug
{Book SeriesPosition}in ebook naming patterns (ebookStandardBookFormat) ignores any:customFormatsuffix, so zero-padding like{Book SeriesPosition:00}silently has no effect. This makes it impossible to match the padded series-index convention several other library tools use (e.g. Kavita/Calibre-style01 - Title), so multi-book series import with inconsistent, non-zero-padded folder names (1 - Title,2 - Title, ...10 - Title), which sorts wrong lexicographically.The generic
:customFormatcapture already exists inFileNameBuilder.TitleRegexand is honored by{PartNumber}/{PartCount}viaFormatPartToken()(value.ToString(customFormat), with asmartmode that pads to the width of the siblingPartCount). But the{Book SeriesPosition}handler inAddBookTokensnever readsTokenMatch.CustomFormatat all:I'd guess this is because
Book.SeriesPositionis astring(to allow values like"2.5"for novellas), so it can't just reuseint.ToString(customFormat)the wayPartNumberdoes — it needs to parse the numeric part first and pad only that, while still passing non-numeric/fractional values through unpadded (or pad only the integer part, e.g.02.5).To Reproduce
naming/examplesAPI) → setebookStandardBookFormatto include{Book SeriesPosition:00 - }{Book Title}.1.1 - Title, not01 - Title.Verified via the naming preview API directly:
(
:0,:00, and made-up suffixes all render identically to no suffix — confirms the token handler discardsCustomFormatentirely rather than rejecting an invalid format.)Expected behavior
{Book SeriesPosition:00}should zero-pad the integer part of the series position to at least 2 digits (1→01,10→10,2.5→02.5), mirroring how{PartNumber:00}/{PartNumber:smart}behave.System Information
FileNameBuilder.csat currentdevelopHEAD)Additional context
Happy to send a PR — the fix looks like a small, self-contained addition to
AddBookTokensthat parses the leading integer fromseriesPosition, appliesint.ToString(customFormat)(or asmartmode) to it, and reattaches any fractional/non-numeric remainder, falling back to the raw string when it isn't a recognizable number. Let me know if that approach sounds right before I put up a PR.