diff --git a/beetsplug/musicbrainz.py b/beetsplug/musicbrainz.py index 137189cdc..4257e52ef 100644 --- a/beetsplug/musicbrainz.py +++ b/beetsplug/musicbrainz.py @@ -792,7 +792,13 @@ class MusicBrainzPlugin(MusicBrainzAPIMixin, MetadataSourcePlugin): self._log.debug("Invalid MBID ({}).", album_id) return None - res = self.mb_api.get_release(albumid, includes=RELEASE_INCLUDES) + # A 404 error here is fine. e.g. re-importing a release that has + # been deleted on MusicBrainz. + try: + res = self.mb_api.get_release(albumid, includes=RELEASE_INCLUDES) + except HTTPNotFoundError: + self._log.debug("Release {} not found on MusicBrainz.", albumid) + return None # resolve linked release relations actual_res = None diff --git a/test/plugins/test_musicbrainz.py b/test/plugins/test_musicbrainz.py index f21c03c97..09127d169 100644 --- a/test/plugins/test_musicbrainz.py +++ b/test/plugins/test_musicbrainz.py @@ -15,10 +15,12 @@ """Tests for MusicBrainz API wrapper.""" import unittest +import uuid from typing import ClassVar from unittest import mock import pytest +import requests from beets import config from beets.library import Item @@ -1106,3 +1108,32 @@ class TestMusicBrainzPlugin(PluginMixin): assert len(candidates) == 1 assert candidates[0].tracks[0].track_id == self.RECORDING["id"] assert candidates[0].album == "hi" + + def test_import_handles_404_gracefully(self, mb, requests_mock): + id_ = uuid.uuid4() + response = requests.Response() + response.status_code = 404 + requests_mock.get( + f"/ws/2/release/{id_}", + exc=requests.exceptions.HTTPError(response=response), + ) + res = mb.album_for_id(str(id_)) + assert res is None + + def test_import_propagates_non_404_errors(self, mb): + class DummyResponse: + status_code = 500 + + error = requests.exceptions.HTTPError(response=DummyResponse()) + + def raise_error(*args, **kwargs): + raise error + + # Simulate mb.mb_api.get_release raising a non-404 HTTP error + mb.mb_api.get_release = raise_error + + with pytest.raises(requests.exceptions.HTTPError) as excinfo: + mb.album_for_id(str(uuid.uuid4())) + + # Ensure the exact error is propagated, not swallowed + assert excinfo.value is error