librespot icon indicating copy to clipboard operation
librespot copied to clipboard

Starting playback of several tracks via their URIs

Open maliavko opened this issue 7 months ago • 5 comments

Description

Starting playback from Spotify Web API for several tracks via list of URIs generates an error response, when the current playback device is Librespot.

{
   "error" : {
     "status" : 403,
     "message" : "Player command failed: Restriction violated",
     "reason" : "UNKNOWN"
   }
}

If the device is official Spotify desktop client or web-page - everything goes well.

Request body example:

{
"uris":["spotify:track:1ZyQEn0iceHj0Lbt6I6Op3"]
}

Version

Built from sources on Windows librespot 0.6.0-dev 8b72954 (Built on 2025-06-02, Build ID: BQcgs54b, Profile: release)

How to reproduce

Steps to reproduce the behavior in librespot e.g.

  1. Launch librespot in win cmd librespot.exe --name test-libre --verbose --access-token ****
  2. Wait for it to connect and register, find a device id and copy: (e.g. in the line Requesting https://gew4-spclient.spotify.com:443/connect-state/v1/devices/732d5f3b265c469083d7da95c8dbc78a1a2711a3?product=0&country=CZ&salt=1045896257) -> 732d5f3b265c469083d7da95c8dbc78a1a2711a3
  3. Open Spotify Web API start-playback endpoint page, put device id copied above and example body: {"uris":["spotify:track:1ZyQEn0iceHj0Lbt6I6Op3"]}
  4. Observer the error response on the page

Log

I am not sure the full log here is really needed, just copying for now the part of the moment of execution of a command in Web, with several lines before and after.

[2025-06-10T13:12:27Z TRACE librespot_core::dealer] Received pong
[2025-06-10T13:12:57Z TRACE librespot_core::dealer] Sent ping
[2025-06-10T13:12:57Z TRACE librespot_core::dealer] Received pong
[2025-06-10T13:13:27Z TRACE librespot_core::session] Sending Pong
[2025-06-10T13:13:27Z TRACE librespot_core::session] keep-alive state: ExpectingPongAck, timeout in 20.0
[2025-06-10T13:13:27Z TRACE librespot_core::session] Received PongAck
[2025-06-10T13:13:27Z TRACE librespot_core::session] keep-alive state: ExpectingPing, timeout in 80.0
[2025-06-10T13:13:27Z TRACE librespot_core::dealer] Sent ping
[2025-06-10T13:13:27Z TRACE librespot_core::dealer] Received pong
[2025-06-10T13:13:57Z TRACE librespot_core::dealer] Sent ping
[2025-06-10T13:13:57Z TRACE librespot_core::dealer] Received pong
[2025-06-10T13:14:10Z TRACE librespot_core::dealer] dealer request hm://connect-state/v1/player/command
[2025-06-10T13:14:10Z TRACE librespot_core::dealer::protocol] message was sent with gzip encoding
[2025-06-10T13:14:10Z TRACE librespot_core::dealer::protocol] websocket request: Object {
        "command": Object {
            "context": Object {
                "pages": Array [
                    Object {
                        "tracks": Array [
                            Object {
                                "uri": String("spotify:track:1ZyQEn0iceHj0Lbt6I6Op3"),
                            },
                        ],
                    },
                ],
            },
            "endpoint": String("play"),
            "logging_params": Object {
                "device_identifier": String("webapi-cfe923b2d660439caf2b557b21f31221"),
            },
            "options": Object {},
            "play_origin": Object {
                "device_identifier": String("webapi-cfe923b2d660439caf2b557b21f31221"),
            },
        },
        "message_id": Number(1509561780),
        "play_on_secondary_stream": Null,
        "sent_by_device_id": String("webapi-cfe923b2d660439caf2b557b21f31221"),
        "target_alias_id": Number(0),
    }
[2025-06-10T13:14:10Z DEBUG librespot_connect::spirc] handling: 'endpoint: play' from webapi-cfe923b2d660439caf2b557b21f31221
[2025-06-10T13:14:10Z ERROR librespot_connect::spirc] failed to handle request: Service unavailable { context had no uri }
[2025-06-10T13:14:10Z DEBUG librespot_core::dealer::manager] replying to ws request: Failure
[2025-06-10T13:14:27Z TRACE librespot_core::session] Received Ping
[2025-06-10T13:14:27Z TRACE librespot_core::session] keep-alive state: PendingPong, timeout in 60.0
[2025-06-10T13:14:27Z DEBUG librespot_core::session] Session strong=6 weak=7
[2025-06-10T13:14:27Z TRACE librespot_core::dealer] Sent ping
[2025-06-10T13:14:27Z TRACE librespot_core::dealer] Received pong
[2025-06-10T13:14:57Z TRACE librespot_core::dealer] Sent ping
[2025-06-10T13:14:57Z TRACE librespot_core::dealer] Received pong

Host (what you are running librespot on):

  • OS: Microsoft Windows [Version 10.0.22631.5335]

Additional context

If I execute the command, connected to some Spotify client - everything goes smooth, and the musics starts. Switching to Librespot later is going right as well.

maliavko avatar Jun 10 '25 13:06 maliavko

403 usually means that there are missing rights to access the endpoint we want to use internally.

Could you try this again with an access-token generated via login5 or with full scope access?

I will look later into it a bit deeper but an initial check if it's permission or logic related would be nice to know :) Thanks in advance

photovoltex avatar Jun 10 '25 13:06 photovoltex

Tho looking at the log it seems more like an obvious logic error. Probably an assumption that was made incorrectly.

photovoltex avatar Jun 10 '25 14:06 photovoltex

It seems to originate from here https://github.com/librespot-org/librespot/blob/dev/connect%2Fsrc%2Fspirc.rs#L992. It might be that the logic broke while merging a different branch into it.

photovoltex avatar Jun 10 '25 14:06 photovoltex

Hey,

If you mean launching librespot with the --enable-oauth option, so I've just tried, paired the app and provided all the acceses throught the web-form, and result is the same.

I have an app registered on Spotify https://developer.spotify.com/ with access to Web API and Playback API, my app goes through auth flow with the scope (not sure how to generate full-access without specifying full list of accesses):

    scope =
        "streaming "
        "playlist-read-private "
        "playlist-read-collaborative "
        "playlist-modify-private "
        "playlist-modify-public "
        "user-top-read "
        "user-read-email "
        "user-read-private "
        "user-read-playback-state "
        "user-read-recently-played "
        "user-read-currently-playing "
        "user-modify-playback-state "
        "user-follow-read "
        "user-follow-modify "
        "user-library-read "
        "user-library-modify";

... and I hand over the access token into librespot process usually.

For the sake of test I obtained a token from their getting started page with the button "Reveal your access token", and got the same error result.

maliavko avatar Jun 10 '25 14:06 maliavko

Oh xD. A very simple bug which most certainly was created unintentionally while merging^^;

Thanks for the find :D

photovoltex avatar Jun 10 '25 15:06 photovoltex