Skip to content

Beets

v2.12.0 Breaking

This release includes breaking changes for platform teams planning a safe upgrade.

✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

cli music music-library musicbrainz python

Summary

AI summary

Broad release touches Bug fixes, New features, Other changes, and https://beets.readthedocs.io/en/stable/plugins/lyrics.html.

Full changelog

New features

  • Convert Plugin: The --force and --keep-new CLI flags are now also available as config options via force and keep_new.

  • import command: The --nomove / -M CLI flag can now be used to override the move: yes config option during import.

  • Lyrics Plugin: Write synced (LRC) lyrics to the SYLT (synchronized lyrics) ID3 frame and plain text to USLT for ID3-tagged files, instead of storing raw LRC timestamps in USLT. Players that only support USLT continue to see readable plain lyrics. :bug: (#6541)

  • ListenBrainz Plugin: Add support for importing ListenBrainz listening history from an export file. Use the -f / --export-file flag to specify the path to the ListenBrainz export file.

  • MusicBrainz Plugin: Introduce aliases_as_credits to make aliases-as-artist-credit optional.

  • Bad Files Plugin: Added settings for auto error and warning actions.

  • Tidal Plugin: New flexible attributes are now populated during imports, including tidal_track_id, tidal_album_id, tidal_artist_id, tidal_track_popularity, tidal_album_popularity, and tidal_updated. Added a new beet tidalsync command to refresh popularity data for imported items by default, or albums with --album, with --force to re-fetch and --write to update file tags.

    Migration: Existing Tidal imports can copy the previously stored IDs into the new flexible attributes with modify command: run beet modify data_source:tidal tidal_album_id='$mb_albumid' -a for albums and beet modify data_source:tidal tidal_track_id='$mb_trackid' for items.

Bug fixes

  • Convert Plugin: Tidy the --playlist help text so it no longer has awkward indentation in CLI output.
  • Duplicates Plugin: Fix plugin output: information about duplicate items was not displayed by default. --count option was ignored :bug: (#6476)
  • FetchArt Plugin: Catch OSError in _set_art so that permission errors (e.g. a file locked by another process) are logged as warnings instead of crashing beets. :bug: (#6193)
  • Fish Plugin: Fix error on plugin initialization.
  • import command: Fix duplicate album merge during import when running in threaded mode. The merge action no longer creates a duplicate folder or reports could not get filesize errors. :bug: (#6601)
  • Lyrics Plugin: Add rate limiting and exponential backoff to HTTP requests to prevent 429 Too Many Requests errors from lyrics sources during bulk imports. :bug: (#6728)
  • Lyrics Plugin: Improve Musica.com lyric scraping so fetched lyrics no longer omit the opening verse or include non-lyric page content.
  • MBSync Plugin / BPSync Plugin: Do not clear items metadata when import.from_scratch is enabled. :bug: (#6613)
  • modify command: Fix beet modify -a splitting multi-value field strings (like artists, genres) into individual characters when modifying albums. Album field types now fall back to the corresponding item field type definitions. :bug: (#5690)
  • move command: move command no longer crashes when an item referenced in the database has been deleted from disk. Missing items are now skipped with a warning and the command continues. :bug: (#6720)
  • MPDStats Plugin: Fix crashes and invalid configuration when passing --host, --port, or --password on the command line. :bug: (#5404)
  • MusicBrainz Collection Plugin: Handle MusicBrainz 401 Unauthorized errors during mbupdate without crashing, and log a clearer message that points users to musicbrainz.user and musicbrainz.pass configuration. :bug: (#6651)
  • MusicBrainz Plugin: Fix KeyError: 'aliases' crash when looking up releases with more than 500 tracks.
  • MusicBrainz Pseudo-Release Plugin: Fix crashes when applying a pseudo-release. One in PseudoAlbumInfo.raw_data and a sqlite3.ProgrammingError.
  • Replace Plugin: Fix TypeError when invoking the Replace Plugin command. :bug: (#6260)
  • Spotify Plugin: Improved Spotify API parsing to handle missing label data :bug: (#6679)
  • Spotify Plugin: Use single instead of double quotes in spotify queries.
  • Tidal Plugin: add Tidal Plugin dependency extra to make sure requests-oauthlib is installed. :bug: (#6633)
  • Tidal Plugin: Fix auth URL not printed in environments without a configured browser :bug: (#6710)
  • AttrDict.__getattribute__ now unmasks AttributeError raised inside a cached_property body. Previously such errors were swallowed by the __getattr__ fallback, producing a misleading message about the property name itself. The wrapped RuntimeError keeps the original traceback so it still points at the real failing line. :bug: (#6558)
  • ReadError and WriteError now include the file path and the underlying reason in their message instead of a <super: ...> object representation. :bug: (#6560)
  • Fix a CLI help formatting regression that moved command descriptions to separate lines; descriptions are inline again, with regression test coverage.
  • Path format queries now correctly match multi-value fields such as genres when using exact string matches like genres:=Classical or genres:=~Classical. :bug: (#6598)

For plugin developers

  • Introduced beets.importer.DuplicateAction to simplify handling of duplicates.
  • Plugin authors can import all autotagger helpers directly from beets.autotag, including match classes, distance helpers, and assign_items, without relying on lower-level autotag modules.

Other changes

  • Lyrics Plugin: Fold rate limiting and 429 retry from the lyrics-specific LyricsSession into the shared beetsplug._utils.requests.TimeoutAndRetrySession so all plugins benefit. The standalone LyricsSession class has been removed.
  • Spotify Plugin: spotifysync now batches its SQLite commit for a sync run, follows the standard beets write-before-store pattern, and logs audio-features API unavailability only once per run.
  • Titlecase Plugin: Correct the path format example and document the %titlecase{text} template function. :bug: (#6697)
  • Log message prefix formatting (musicbrainz: msg) moved from a filter to LegacyFormatter, making future customization easier.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track Beets

Get notified when new releases ship.

Sign up free

About Beets

Music library manager and MusicBrainz tagger (command-line and Web interface).

All releases →

Related context

Beta — feedback welcome: [email protected]