Releases: linuxserver/docker-beets
2.11.0-ls332
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/2.11.0-ls332/index.html
LinuxServer Changes:
Full Changelog: 2.11.0-ls331...2.11.0-ls332
Remote Changes:
Updating PIP version of beets to 2.11.0
nightly-da16db11-ls290
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-da16db11-ls290/index.html
LinuxServer Changes:
Full Changelog: nightly-6dd62516-ls289...nightly-da16db11-ls290
Remote Changes:
docs: adding beets-getlrc to the 'other plugins' list (#6664)
Description
I added a plugin i made to the docs (index.rst). I made sure to add a
link to my github repo for the project. Nothing else was changed.
nightly-6dd62516-ls289
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-6dd62516-ls289/index.html
LinuxServer Changes:
Full Changelog: nightly-4746d852-ls288...nightly-6dd62516-ls289
Remote Changes:
Fix album modify splitting multi-value field strings into individual characters (#6653)
Fixes #5690
Problem
When running beet mod -a artists=Charli XCX in album mode, the
artists tag value gets split into individual characters on disk. Item
mode (beet mod without -a) works correctly.
Root Cause
Album._type(artists)returnsDEFAULT(artists is not an Album
fixed field), soAlbum._parsereturns a plain string.- When
Album.store()propagates to items,
MULTI_VALUE_DSV.normalize(value)falls through tomodel_type(value)
=list(value), splitting the string into characters.
Fix
DelimitedString.normalize(types.py): Handle string input by
parsing it (splitting by delimiter if present) instead oflist(). This
prevents character-level splitting.Model._type(db.py): Fall back to the related models field
definitions so multi-value types (e.g.MULTI_VALUE_DSVforartists)
are recognized on both Album and Item models.
nightly-c9df7a94-ls288
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-c9df7a94-ls288/index.html
LinuxServer Changes:
No changes
Remote Changes:
fix(hooks): chain original error when cached_property AttrDict lookup fails (#6558) (#6564)
Fixes #6558.
Problem
When a cached_property on an AttrDict subclass raises
AttributeError during its own computation, Python's attribute lookup
falls back to __getattr__ with the property's own name. That masks the
real missing field behind a misleading traceback like:
AttributeError: 'AlbumInfo' object has no attribute 'raw_data'
…even though raw_data exists on the instance and the code inside
raw_data is what blew up on a missing sibling attribute. Users and
maintainers hit this both on #6558 and on the earlier #6503 / #6506
reports (different metadata providers, same masking shape).
Fix
In AttrDict.__getattr__, if the looked-up class attribute is a
cached_property, invoke it explicitly. If it raises AttributeError,
re-raise as RuntimeError with from exc so the original cause is
preserved on the traceback and names the attribute that actually failed.
Plain missing-attribute behaviour (obj.nope on an AttrDict) is
unchanged — that still raises AttributeError as before.
Tests
Added a regression class TestAttrDictCachedPropertyMasking in
test/autotag/test_hooks.py covering:
- real missing attr in a
cached_propertybody surfaces as
RuntimeErrornaming the missing field - the
RuntimeError.__cause__is the originalAttributeError - a plain missing attr on an
AttrDictstill raisesAttributeError - existing dict-key access (
obj.title) still works
Full test/autotag/test_hooks.py suite: 90 passed locally.
Follow-up
Picked approach (1) from @snejus' comment on #6558
(beetbox/beets#6558 (comment)).
Happy to iterate on the exception type or wording.
nightly-4746d852-ls288
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-4746d852-ls288/index.html
LinuxServer Changes:
Full Changelog: nightly-aa33b1cb-ls287...nightly-4746d852-ls288
Remote Changes:
core/structure: create a separate module for sorting in dbcore (#6644)
This PR moves all sorting-related classes from beets.dbcore.query into
a new dedicated module, beets.dbcore.sort. All references and imports
throughout the codebase and tests are updated to use the new module. No
functional changes are introduced - this is a mechanical refactor to
improve code organization and separation of concerns.
High-level impact:
- Sorting logic is now isolated in
beets.dbcore.sort, making the
architecture clearer. - All code using sort classes (e.g.,
Sort,FixedFieldSort,
MultipleSort, etc.) now imports them frombeets.dbcore.sortinstead
ofbeets.dbcore.query. - No changes to public APIs or behavior; only import paths and module
boundaries are affected.
This change lays groundwork for future maintainability and makes the
codebase easier to navigate for contributors.
nightly-fc9c02a4-ls287
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-fc9c02a4-ls287/index.html
LinuxServer Changes:
No changes
Remote Changes:
Fix command desc formatting in help (#6646)
No impact on core logic, only on CLI help output formatting.
This PR fixes the formatting of command descriptions in the CLI help
output.
- Command descriptions had historically been printed inline, however
9352a79 introduced a bug which moved them to the next line, making the
help output very verbose. - Now, descriptions again appear inline with the command name (e.g.,
config show or edit the user configuration), improving readability and
consistency. - A regression test (
test_help) is included to verify the new output
format and prevent future breakage.
High-level impact: CLI help output is more user-friendly, with no effect
on core logic or APIs.
Before
After
nightly-aa33b1cb-ls287
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-aa33b1cb-ls287/index.html
LinuxServer Changes:
Full Changelog: nightly-44f7bf80-ls286...nightly-aa33b1cb-ls287
Remote Changes:
fix: duplicate album merge broken in threaded import mode (#6623)
Fixes #6601
Added import contextvars and changed _extend_pipeline to capture the
current context and run the inner pipeline within it to ensure the
music_dir context variable is available when the inner pipeline
resolves paths, preventing the relative-path bug that caused could not
get filesize errors and removing 0 old duplicated items during merge.
Works perfectly after the fix:
arsaboo@arsmusic:~$ beet import -m -I -t ~/shared/music/ --set genre="Filmi" --search-id 7MwKD3kEFMov4LQqyhnmzL
/home/arsaboo/shared/music (1 items)
Match (75.2%):
King - Lukkhe
≠ artist, tracks
Spotify, None, 2026, None, Warner Music India, None, None
https://open.spotify.com/album/7MwKD3kEFMov4LQqyhnmzL
≠ Artist: King; OAFF; Savera; Sunny M.R. -> King
* Album: Lukkhe
≠ (#2) Khamoshiyaan (3:03) -> (#2) Khamoshiyaan (feat. Romy & Manreet Khara) (3:03)
Missing tracks (13/14 - 92.9%):
! Bulletproof (#1) (3:09)
! Jee Lenge (#3) (3:25)
! Headshot (#4) (3:10)
! Ruh Teri (feat. Manreet Khara & Agrim Joshi) (#5) (2:31)
! Roobaroo (#6) (3:17)
! Savere (#7) (2:29)
! Haal (#8) (3:29)
! Haal (The Journey) (#9) (6:13)
! Nachdi Shaam (#10) (2:22)
! Hoga Bada Mera Naam (#11) (1:58)
! All Eyes On Us (#12) (3:13)
! Swan Song (Hoya Azaad) (#13) (3:17)
! Bhaari Pangey (#14) (2:19)
➜ [A]pply, More candidates, Skip, Use as-is, as Tracks, Group albums,
Enter search, enter Id, aBort, eDit, edit Candidates, Print tracks,
Open files with Picard? a
This album is already in the library!
Old: 3 items, MP3, 320kbps, 9:45, 22.9 MiB
New: 1 items, MP3, 320kbps, 3:03, 7.8 MiB
➜ [S]kip new, Keep all, Remove old, Merge all? m
/home/arsaboo/shared/music
/data/music/Hindi Music/L/Lukkhe [30718] (2026)/Lukkhe (2026) - Bulletproof.mp3
/data/music/Hindi Music/L/Lukkhe [30718] (2026)/Lukkhe (2026) - Headshot.mp3
/data/music/Hindi Music/L/Lukkhe [30718] (2026)/Lukkhe (2026) - Jee Lenge.mp3 (4 items)
Match (82.6%):
King - Lukkhe
≠ artist, tracks
Spotify, None, 2026, None, Warner Music India, None, None
https://open.spotify.com/album/7MwKD3kEFMov4LQqyhnmzL
≠ Artist: OAFF; Savera; Ruaa Kayy; Romy; Manreet Khara -> King
* Album: Lukkhe
* (#1) Bulletproof (3:09)
≠ (#2) Khamoshiyaan (3:03) -> (#2) Khamoshiyaan (feat. Romy & Manreet Khara) (3:03)
* (#3) Jee Lenge (3:25)
* (#4) Headshot (3:10)
Missing tracks (10/14 - 71.4%):
! Ruh Teri (feat. Manreet Khara & Agrim Joshi) (#5) (2:31)
! Roobaroo (#6) (3:17)
! Savere (#7) (2:29)
! Haal (#8) (3:29)
! Haal (The Journey) (#9) (6:13)
! Nachdi Shaam (#10) (2:22)
! Hoga Bada Mera Naam (#11) (1:58)
! All Eyes On Us (#12) (3:13)
! Swan Song (Hoya Azaad) (#13) (3:17)
! Bhaari Pangey (#14) (2:19)
➜ [A]pply, More candidates, Skip, Use as-is, as Tracks, Group albums,
Enter search, enter Id, aBort, eDit, edit Candidates, Print tracks,
Open files with Picard? anightly-d741a464-ls286
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-d741a464-ls286/index.html
LinuxServer Changes:
Full Changelog: nightly-5df37abc-ls285...nightly-d741a464-ls286
Remote Changes:
core/structure: move UserError to beets.exceptions (#6643)
Update all references in core, plugins, and tests to import UserError
from the new location. This centralizes exception handling and improves
code organization.
nightly-44f7bf80-ls286
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/nightly-44f7bf80-ls286/index.html
LinuxServer Changes:
No changes
Remote Changes:
Fix path format queries for multi-valued fields (#6635)
Fixes #6598.
the issue was that path format queries are evaluated against an
in-memory Item using query.match(), where multi-valued fields such as
genres are represented as lists, e.g. ["Classical"]. Before this change,
string/exact matching treated that list as one whole value, so a path
rule like genres:=~Classical: _Classical/... failed to match and fell
back to the default path format, even though beet list
genres:=~Classical worked through the database query path. This change
updates in-memory matching so sequence-like field values are matched
element by element, while excluding strings and byte-like values from
sequence handling. I added regression tests for genres:=~Classical,
genres:=Classical, avoiding a false positive for Neoclassical, and
direct query.match() behavior on multi-valued fields. Manual
verification showed the original version returned match: False and
destination: ...\one\two, while the fixed version returns match: True
and destination: ...\one\three.
Summary
This fixes path format selection for multi-valued fields such as
genres.
Path format queries are evaluated against an in-memory Item via
query.match().
For multi-valued fields, the in-memory value is a list, for example:
genres = ["Classical"]2.11.0-ls331
CI Report:
https://ci-tests.linuxserver.io/linuxserver/beets/2.11.0-ls331/index.html
LinuxServer Changes:
Full Changelog: 2.11.0-ls330...2.11.0-ls331
Remote Changes:
Updating PIP version of beets to 2.11.0

