Skip to content

fix(discogs): retry malformed search responses - #6912

Open
treyturner wants to merge 1 commit into
beetbox:masterfrom
treyturner:fix/discogs-json-retry
Open

fix(discogs): retry malformed search responses#6912
treyturner wants to merge 1 commit into
beetbox:masterfrom
treyturner:fix/discogs-json-retry

Conversation

@treyturner

@treyturner treyturner commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Retry Discogs searches once when the API returns an invalid JSON response. If the retry also fails, flow through existing error handling. Includes regression tests for successful recovery and retry exhaustion.

Reference: joalla/discogs_client#163

Originating stack trace:

discogs: Error searching Discogs: Expecting value: line 1 column 1 (char 0)
Traceback (most recent call last):
  File "/usr/local/lib/python3.14/site-packages/beets/metadata_plugins.py", line 420, in _search_api
    response_data = self.get_search_response(params)
  File "/usr/local/lib/python3.14/site-packages/beetsplug/discogs/__init__.py", line 297, in get_search_response
    return [r.data for r in results.page(1)]
                            ~~~~~~~~~~~~^^^
  File "/usr/local/lib/python3.14/site-packages/discogs_client/models.py", line 347, in page
    data = self.client._get(self._url_for_page(index))
  File "/usr/local/lib/python3.14/site-packages/discogs_client/client.py", line 115, in _get
    return self._request('GET', url)
           ~~~~~~~~~~~~~^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/site-packages/discogs_client/client.py", line 107, in _request
    body = json.loads(content)
  File "/usr/local/lib/python3.14/json/__init__.py", line 352, in loads
    return _default_decoder.decode(s)
           ~~~~~~~~~~~~~~~~~~~~~~~^^^
  File "/usr/local/lib/python3.14/json/decoder.py", line 345, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.14/json/decoder.py", line 363, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

Testing

  • Full test suite on Python 3.14
  • Ruff, mypy, and Sphinx lint

To Do

  • Documentation. (If you've added a new command-line flag, for example, find the appropriate page under docs/ to describe it.)
  • Changelog. (Add an entry to docs/changelog.rst to the bottom of one of the lists near the top of the document.)
  • Tests. (Very much encouraged but not strictly required.)

@treyturner
treyturner requested a review from a team as a code owner August 5, 2026 22:19
@github-actions github-actions Bot added the discogs discogs plugin label Aug 5, 2026
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.77%. Comparing base (dc1709e) to head (afd07ce).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6912      +/-   ##
==========================================
+ Coverage   75.74%   75.77%   +0.03%     
==========================================
  Files         164      164              
  Lines       21437    21443       +6     
  Branches     3379     3379              
==========================================
+ Hits        16237    16248      +11     
+ Misses       4400     4396       -4     
+ Partials      800      799       -1     
Files with missing lines Coverage Δ
beetsplug/discogs/__init__.py 69.48% <100.00%> (+1.48%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@treyturner
treyturner force-pushed the fix/discogs-json-retry branch from 15359b3 to afd07ce Compare August 11, 2026 21:09
@semohr

semohr commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This seems like something to me that could be part of the discogs_client instead. @JOJ0 Assigning you here since this seems to be right in your expertise 🙃

@semohr
semohr requested a review from JOJ0 August 12, 2026 09:11
@henry-oberholtzer

henry-oberholtzer commented Aug 13, 2026

Copy link
Copy Markdown
Member

The code for this PR looks good to me! I think my question is whether immediately retrying a query immediately after a failure seems to actually yield results after a json.decode() error.

If it's an outage on the discogs server side, my instinct is that it won't fix it, but I could be totally wrong if anyone has anecdotal experience with this issue.

It's also hard to test if a re-search actuallr recovers errors from discogs since it seems to be a white whale issue - none of this is to say we shouldn't try to give a query another shot in a failure.

EDIT:

Well, anecdotally - it seems to resolve it according to this post: joalla/discogs_client#163 (comment)

@henry-oberholtzer henry-oberholtzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks simple enough. I'll let another maintainer just re-confirm since I've been away from the project for a minute. :)

@treyturner

Copy link
Copy Markdown
Contributor Author

It's also hard to test if a re-search actually recovers errors

My anecdotal experience is also that a retry returns success, but that's usually after at least a few seconds following an abort and restart of the current import. We may find success to be less likely when immediately retried. I added a log line indicating the retry so that we can later evaluate if a small sleep between attempts may increase the chance of success.

@treyturner

Copy link
Copy Markdown
Contributor Author

This seems like something to me that could be part of the discogs_client instead.

I can definitely appreciate this take. I considered that approach as well, but given the discussion and apparent ambiguity in joalla/discogs_client#163, I thought this one small effort upstream could protect the user experience while discogs_client continues working through opportunities to improve consistency. If it required really anything else here in beets I'd not have been comfortable proposing it.

Still, I completely understand if this is desired downstream instead. Thanks for your consideration!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

discogs discogs plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants