From e79bc9861d47ff5a90fede089f8983337259422d Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Fri, 24 Jul 2026 17:41:52 -0700 Subject: [PATCH 1/3] fix: skip metadata source search when query and filters are empty Items with no artist or title tags produce a search with an empty query and no filters. The request was still sent to the metadata source API, and MusicBrainz answers it with a 400 Bad Request, which was logged with a traceback once per affected file during an import. Return no candidates instead of issuing a request that cannot match anything. --- beets/metadata_plugins.py | 7 +++++++ docs/changelog.rst | 4 ++++ test/test_metadata_plugins.py | 8 ++++++++ 3 files changed, 19 insertions(+) diff --git a/beets/metadata_plugins.py b/beets/metadata_plugins.py index e116d1d520..6d285fe804 100644 --- a/beets/metadata_plugins.py +++ b/beets/metadata_plugins.py @@ -412,6 +412,13 @@ def _search_api( if self.config["search_query_ascii"].get(): query = unidecode.unidecode(query) + if not query and not filters: + # Items without usable metadata produce an empty search request, + # which APIs reject (e.g. MusicBrainz answers with a 400). Report + # no candidates instead of making a doomed request. + self._log.debug("Skipping search with empty query and filters") + return () + limit = self.config["search_limit"].get(int) params = SearchParams(query_type, query, filters, limit) diff --git a/docs/changelog.rst b/docs/changelog.rst index acbd3294fe..718727752d 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -95,6 +95,10 @@ Bug fixes valid date/time string" error instead of crashing with an uncaught ``KeyError``. A ``|`` was being accepted as a relative-date unit due to a regular expression character-class typo. +- Metadata source searches with neither a query nor any filters (for example + items with no artist and title tags) no longer hit the API, which rejected + them with an error such as MusicBrainz' ``400 Bad Request``. Such searches + now report no candidates instead. :bug:`6862` .. For plugin developers diff --git a/test/test_metadata_plugins.py b/test/test_metadata_plugins.py index 8f57ddbd9f..4d677989fe 100644 --- a/test/test_metadata_plugins.py +++ b/test/test_metadata_plugins.py @@ -127,6 +127,14 @@ def test_search_api_raises_when_raise_on_error_enabled( with pytest.raises(ValueError, match="Search failure"): search_plugin._search_api("track", "query", {}) + def test_search_api_skips_request_without_query_and_filters( + self, config, search_plugin + ): + """Empty searches are rejected by APIs, so do not send them.""" + config["raise_on_error"] = True + + assert search_plugin._search_api("track", "", {}) == () + def test_albums_for_ids_calls_each_plugin_once(monkeypatch): start_workers = Event() From 98fdff67ae8fbaab57d7f7d546f77c9193deb832 Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Thu, 30 Jul 2026 05:38:48 -0700 Subject: [PATCH 2/3] docs: scope changelog entry to SearchApiMetadataSourcePlugin plugins --- docs/changelog.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 718727752d..34296f95a4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -95,10 +95,12 @@ Bug fixes valid date/time string" error instead of crashing with an uncaught ``KeyError``. A ``|`` was being accepted as a relative-date unit due to a regular expression character-class typo. -- Metadata source searches with neither a query nor any filters (for example - items with no artist and title tags) no longer hit the API, which rejected - them with an error such as MusicBrainz' ``400 Bad Request``. Such searches - now report no candidates instead. :bug:`6862` +- Plugins built on ``SearchApiMetadataSourcePlugin`` (:doc:`plugins/musicbrainz`, + :doc:`plugins/spotify`, :doc:`plugins/deezer` and :doc:`plugins/discogs`) no + longer send a search request when both the query text and the filters are + empty, as happens for items with no artist and title tags. Such a request + cannot match anything and MusicBrainz rejects it with ``400 Bad Request``; + these searches now report no candidates instead. :bug:`6862` .. For plugin developers From 6ec0eb0e71aa92fb49b3f7702789d7b4569eff3f Mon Sep 17 00:00:00 2001 From: Sanjay Santhanam <51058514+Sanjays2402@users.noreply.github.com> Date: Sun, 2 Aug 2026 02:02:42 -0700 Subject: [PATCH 3/3] Simplify empty-search comment and shorten changelog entry --- beets/metadata_plugins.py | 3 --- docs/changelog.rst | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/beets/metadata_plugins.py b/beets/metadata_plugins.py index 6d285fe804..124d4ab4e8 100644 --- a/beets/metadata_plugins.py +++ b/beets/metadata_plugins.py @@ -413,9 +413,6 @@ def _search_api( query = unidecode.unidecode(query) if not query and not filters: - # Items without usable metadata produce an empty search request, - # which APIs reject (e.g. MusicBrainz answers with a 400). Report - # no candidates instead of making a doomed request. self._log.debug("Skipping search with empty query and filters") return () diff --git a/docs/changelog.rst b/docs/changelog.rst index 34296f95a4..f31711003c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -98,9 +98,7 @@ Bug fixes - Plugins built on ``SearchApiMetadataSourcePlugin`` (:doc:`plugins/musicbrainz`, :doc:`plugins/spotify`, :doc:`plugins/deezer` and :doc:`plugins/discogs`) no longer send a search request when both the query text and the filters are - empty, as happens for items with no artist and title tags. Such a request - cannot match anything and MusicBrainz rejects it with ``400 Bad Request``; - these searches now report no candidates instead. :bug:`6862` + empty. :bug:`6862` .. For plugin developers