ExportXMLWordPrintable

    • Type: Bug
    • Resolution: Unresolved
    • Priority: Normal
    • None
    • Component/s: troi
    • None

      Description

      Exporting a ListenBrainz playlist to SoundCloud consistently fails with HTTP 500.

      The ListenBrainz API request:

      POST /1/playlist/\{playlist_mbid}/export/soundcloud
      

      returns:

      500 Internal Server Error
      

      The browser console also reports:

      POST https://api.listenbrainz.org/1/playlist/\{playlist_mbid}/export/soundcloud
      500
      
      net::ERR_CONNECTION_CLOSED
      

      Reproduction

      1. Connect a SoundCloud account to ListenBrainz.
      2. Open a ListenBrainz playlist.
      3. Select "Export to SoundCloud".
      4. Observe HTTP 500 from the playlist export endpoint.

      Example playlist MBID:

      69575158-4bf4-4a76-9074-8fff8858558d
      

      Root cause

      The SoundCloud export path calls:

      TransferPlaylistPatch
      → PlaylistFromJSPFElement
      → PlaylistElement.submit_to_soundcloud()
      → tools.soundcloud_lookup.submit_to_soundcloud()
      → SoundcloudAPI.add_playlist_tracks()
      → http_put()
      → http_fetch(url, "PUT")
      

      In troi/http_request.py, http_put() explicitly calls http_fetch() with the PUT method:

      def http_put(url, headers=None, params=None, **kwargs):
          """ Convenience function for http put"""
          return http_fetch(
              url,
              "PUT",
              headers=headers,
              params=params,
              **kwargs
          )
      

      However, http_fetch() explicitly rejects every method except GET and POST:

      if method not in ("GET", "POST"):
          raise ValueError("Only GET and POST are supported.")
      

      Therefore http_put() deterministically raises:

      ValueError: Only GET and POST are supported.
      

      There is an additional dispatch issue in the same function:

      if method == "GET":
          r = session.get(url, params=params, headers=headers, **kwargs)
      else:
          r = session.post(url, params=params, headers=headers, **kwargs)
      

      Even if PUT were added to the allowed-method check, PUT would currently be dispatched as POST.

      Minimal reproduction

      from troi.http_request import http_put
      
      http_put("https://example.com")
      

      Expected:

      A PUT request is performed.

      Actual:

      ValueError: Only GET and POST are supported.
      

      Suggested fix

      Explicitly support PUT in http_fetch():

      if method not in ("GET", "POST", "PUT"):
          raise ValueError("Only GET, POST and PUT are supported.")
      
      if method == "GET":
          r = session.get(url, params=params, headers=headers, **kwargs)
      elif method == "POST":
          r = session.post(url, params=params, headers=headers, **kwargs)
      else:
          r = session.put(url, params=params, headers=headers, **kwargs)
      

      Alternatively, use the generic requests method dispatcher:

      if method not in ("GET", "POST", "PUT"):
          raise ValueError(f"Unsupported HTTP method: \{method}")
      
      r = session.request(
          method,
          url,
          params=params,
          headers=headers,
          **kwargs
      )
      

      Current source

      Repository:

      metabrainz/troi-recommendation-playground
      

      File:

      troi/http_request.py
      

      The current main branch defines http_put() but http_fetch() only permits GET and POST.

      Environment

      ListenBrainz production

      Observed: July 2026

      Browser: Google Chrome 150 / Windows

      Export target: SoundCloud

      Notes

      I searched the Troi GitHub issues and pull requests for "http_put" and the exact exception text "Only GET and POST are supported" and did not find an existing issue or PR covering this bug.

            Assignee:
            Robert Kaye
            Reporter:
            infesta
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated:

                Version Package