Skip to content

Hourly Spotify session storms cause repeated audio-key timeouts and zone unavailability with many zones #252

Description

@tobsch

Summary

When many zones each have their own librespot device (i.e. inputs.spotify.offload=false on all/most zones), Spotify-side disruptions arrive as synchronized 11-event bursts roughly every 60–110 minutes that knock all zones offline simultaneously and trip the rapid-failure cooldown introduced in #244.

After the recent beta-latest digest c7cb9f… (incl. #240 + #244), the engine no longer wedges — recovery via cooldown+retry is working as designed. But during each burst, all zones are unplayable for ~5+ minutes, and the bursts repeat all day.

Environment

  • Image: ghcr.io/lox-audioserver/lox-audioserver:beta-latest digest sha256:c7cb9fd747e40c057e3ef8d83fefe31b940cd8833212c62bd4bb246dc39dad44 (post-fix: retry spotify connect restart after cooldown failure #244)
  • 11 zones, all with inputs.spotify.enabled=true, all with inputs.spotify.offload=false
  • Single Spotify Premium account → 11 simultaneous Spotify Connect devices registered to one account
  • Network connectivity to Spotify endpoints from the container is healthy (apresolve.spotify.com returns 200)

Observed cadence (real production data, last 36h)

11 distinct burst windows. Each burst = exactly 11 simultaneous errors (= one per zone):

Start UTC Errors Gap from previous
2026-04-30 17:49:37 11
2026-04-30 18:16:27 11 +26 min
2026-04-30 19:24:42 11 +68 min
2026-04-30 21:16:36 11 +111 min
2026-04-30 22:16:41 11 +60 min
2026-04-30 23:27:51 11 +71 min
2026-05-01 00:55:06 11 +87 min
2026-05-01 02:43:46 11 +108 min
2026-05-01 05:51:58 12 +188 min
2026-05-01 05:55:00 12 +3 min
2026-05-01 05:59:44 24 +4 min

The fact that every burst is exactly 11 events, one per zone, within the same second is the smoking gun: this is account-wide, not per-zone — Spotify is disrupting every Connect device on the account at once.

Error pattern in each burst

Per zone within a burst:

[ERROR] librespot_core::session  Connection to server closed.
[ERROR] librespot_core::dealer::manager  failed sending dealer request channel closed
[ERROR] librespot_core::audio_key  Audio key response timeout
[ERROR] librespot_playback::player  Unable to read audio file: Symphonia Decoder Error: end of stream
[WARN]  Zones|Manager  reason='spotify Audio key response timeout' playback error
[WARN]  Input|Spotify  attempts=11 windowMs=30000  spotify connect restart suppressed after repeated failures

The audio-key timeout fires near-simultaneously across zones, the player bails on the encrypted segment, and the spirc reconnects from the dealer channel close. After 11 such events in 30s, #244's suppression kicks in (correctly).

What's working

What's still broken (the user-visible bug)

During each ~5-min cooldown window, all zones report "playback error" and audio cannot be initiated. With 11 bursts/36h, that's ~55 minutes/day of unplayable state, distributed across the day. From the user's perspective: "I press Play and nothing happens" several times a day.

Hypothesis on root cause

Eleven independent librespot Connect devices all live-attached to one Spotify account is well above what most listeners produce. We suspect Spotify's backend periodically performs an account-wide reset/rebalance (token refresh, dealer-region rotation, etc.) and disrupts all sessions simultaneously. This is not a librespot bug per se — librespot is correctly reconnecting — but the count of simultaneous devices is what makes the disruption visible and synchronized.

This matches what we'd expect from rate-limit / fair-use behavior: the more devices you stack on one account, the more attractive a target your account is for periodic resets.

Proposed fix

Make inputs.spotify.offload=true the default for new zones, and surface this in docs/admin UI:

  1. With offload, only the primary zone runs librespot; the other zones receive audio via the internal output bus.
  2. Reduces librespot device count from N (= number of zones) to 1 per Spotify-enabled bridge.
  3. Eliminates the synchronized-burst surface area entirely; a single-device account is far less likely to be disrupted.
  4. Matches the multiroom pattern used by Squeezebox/Snapcast/Music Assistant.

Specific suggestions:

  • Schema default: change the offload default from false to true in extractZonesFromPayload() / defaultZoneInputs() so new zones built from the Miniserver descriptor get offload enabled
  • Migration: on container start, if there are >3 Spotify-enabled zones with offload=false and they share the same accounts[] entry, log a warning recommending offload
  • Admin UI: add a tooltip on the offload toggle explaining the trade-off (per-zone Spotify Connect device vs. centralized routing) and that offload is recommended for installs with >3 zones on one account
  • Docs: add a "How many Spotify Connect devices is too many?" section to the wiki/README

Why this isn't fully solvable inside librespot

Even if librespot's reconnect loop were perfect, Spotify's account-side behavior would still produce visible gaps during reconnect. The only durable mitigation is reducing the device count, which has to happen at the lox-audioserver layer (since lox-audioserver decides how many librespot instances to spawn).

Workaround for affected users today

In data/config.json, edit each zone's inputs.spotify.offload: falsetrue for all but one zone. Restart container.

Repro

Set up ≥10 zones, all with inputs.spotify.enabled=true and inputs.spotify.offload=false. Run for >12 hours. Observe burst pattern in container logs.


Happy to share full anonymized logs or test patches.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions