Added
- API client error context - every Radarr / Sonarr / Prowlarr / Jellyseerr / qBittorrent client now exposes a
getLastError()method that returns the HTTP code, method, path and the actual error message extracted from the upstream response body (Radarr'serrorMessage, Symfony validation errors, etc.). Reset between worker requests viaResetInterface. - Circuit breaker on every API client - once a service times out or refuses connection during a request, the same client short-circuits all subsequent calls in the same request and returns
nullinstantly instead of letting them stack up. Reset between worker requests viaResetInterface. Preventsmax_execution_time exceededfatals when an upstream service goes down. - Cross-request "service down" cache - when an API client hits a network timeout (curl error, no HTTP response at all), it persists "service X is down" in the filesystem cache pool with a 30 s TTL. Subsequent page loads check this cache first and short-circuit instantly (0 ms) instead of paying another 4 s timeout. After 30 s the cache expires and the next page load tries once. On any successful response the cache is cleared. Without this, every navigation paid the 4 s connect timeout because FrankenPHP workers reset the in-process circuit breaker between requests - making any LAN service outage feel like an app-wide freeze.
Changed
- LAN-only API clients (Radarr / Sonarr / Prowlarr / Jellyseerr / qBittorrent) now use a tighter timeout: 2 s connect / 4 s total (was 10 s) and
CURLOPT_NOSIGNAL=1. Combined with the circuit breaker, a downed service caps page load at ~4 s instead of timing out PHP after 30 s. Internet-facing clients (TMDb, Gluetun) keep their longer timeouts (8 s / 15 s).
Fixed
- Mutating actions in the Radarr / Sonarr / Prowlarr / Jellyseerr / qBittorrent UI now surface the upstream error in a flash message instead of redirecting silently. Users see exactly which API call failed, the HTTP code returned and the original error message - no more "I deleted a quality profile and nothing happened, did it work?" mystery. JSON endpoints also return a structured
{error, http_code, service}payload on failure.