Radarr/Radarr · error · ImportListException
Simkl API call resulted in an unexpected StatusCode [{0}]
Error message
Simkl API call resulted in an unexpected StatusCode [{0}] What it means
SimklParser.PreProcess rejects the Simkl API HTTP response when its status code is not 200 OK. It is a hard precondition gate: if the upstream Simkl endpoint returned any non-OK status (4xx/5xx/redirect), parsing is skipped entirely and an ImportListException is thrown so the import run fails fast instead of deserializing a likely-empty or error body.
Source
Thrown at src/NzbDrone.Core/ImportLists/Simkl/SimklParser.cs:76
foreach (var movie in jsonResponse.Movies)
{
movies.AddIfNotNull(new ImportListMovie
{
Title = movie.Movie.Title,
TmdbId = int.TryParse(movie.Movie.Ids.Tmdb, out var tmdbId) ? tmdbId : 0,
ImdbId = movie.Movie.Ids.Imdb,
});
}
}
return movies;
}
protected virtual bool PreProcess(ImportListResponse netImportResponse)
{
if (netImportResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new ImportListException(netImportResponse, "Simkl API call resulted in an unexpected StatusCode [{0}]", netImportResponse.HttpResponse.StatusCode);
}
if (netImportResponse.HttpResponse.Headers.ContentType != null && netImportResponse.HttpResponse.Headers.ContentType.Contains("text/json") &&
netImportResponse.HttpRequest.Headers.Accept != null && !netImportResponse.HttpRequest.Headers.Accept.Contains("text/json"))
{
throw new ImportListException(netImportResponse, "Simkl API responded with html content. Site is likely blocked or unavailable.");
}
return true;
}
}
}
View on GitHub (pinned to ca451608dc)
Solutions
- Re-authenticate the Simkl account / refresh the token in the import list settings and retry.
- Open the exact Simkl endpoint URL in a browser to see the real status/body (401 vs 429 vs 500 narrows the cause).
- If 429, wait and reduce the import sync interval; Simkl is rate-limiting the requests.
- Verify the configured Simkl username/list type is valid for the account.
- Check network egress (proxy/DNS) can reach api.simkl.com without an intermediary returning a non-OK status.
Example fix
// before: hard failure on any non-OK status
if (netImportResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
throw new ImportListException(...);
// after: tolerate transient 5xx/429 and surface auth errors distinctly
var sc = netImportResponse.HttpResponse.StatusCode;
if (sc == HttpStatusCode.Unauthorized || sc == HttpStatusCode.Forbidden)
throw new ImportListException(netImportResponse, $"Simkl auth failed ({sc}). Re-link the account.");
if ((int)sc is 429 or >= 500)
throw new RequestLimitReachedException($"Simkl unavailable/rate-limited ({sc}). Retry later.");
if (sc != HttpStatusCode.OK)
throw new ImportListException(netImportResponse, $"Simkl unexpected status {sc}"); Defensive patterns
Strategy: try-catch
Validate before calling
// Validate Simkl credentials and reachability before triggering an import run.
if (string.IsNullOrWhiteSpace(settings.BaseUrl)) return ConfigError("BaseUrl missing");
if (string.IsNullOrWhiteSpace(settings.AccessToken)) return ConfigError("Simkl token missing");
// optional liveness probe:
// var probe = await httpClient.GetAsync($"{settings.BaseUrl}/users/settings");
// if (!probe.IsSuccessStatusCode) return ConfigError($"Simkl probe status {probe.StatusCode}"); Type guard
// Determine whether a Simkl response is safe to parse (status OK and not the html-block case).
bool IsParseableSimklResponse(ImportListResponse r)
=> r.HttpResponse.StatusCode == HttpStatusCode.OK
&& !(r.HttpResponse.Headers.ContentType?.Contains("text/json") == true
&& r.HttpRequest.Headers.Accept?.Contains("text/json") != true); Try / catch
try { return _parser.ParseResponse(listResponse); }
catch (ImportListException ex) when (ex.Message.Contains("Simkl API call"))
{
var code = listResponse.HttpResponse.StatusCode;
if (code == HttpStatusCode.Unauthorized || code == HttpStatusCode.Forbidden)
throw new ImportListException(listResponse, "Simkl auth failed ({0}). Re-link the account.", code);
if ((int)code == 429 || (int)code >= 500)
return Array.Empty<ImportListResponse>(); // transient: treat as empty this run
throw;
} Prevention
- Keep the Simkl OAuth token fresh; re-link on any 401.
- Probe the endpoint after config changes.
- Throttle syncs to avoid 429s.
When it happens
Trigger: A Simkl import list fetch returns a non-200 status: expired/invalid OAuth token (401), bad request (400), rate limiting (429), Simkl maintenance/5xx, or a network proxy returning a 502. The status code is interpolated into the message.
Common situations: Simkl auth token expired or revoked; Simkl user/username setting wrong causing 4xx; transient Simkl outage; corporate proxy rewriting responses; the Simkl API base URL was overridden to a wrong endpoint.
Related errors
- StevenLu API call resulted in an unexpected StatusCode [{0}]
- Simkl API responded with html content. Site is likely blocke
- TMDb API call resulted in an unexpected StatusCode [{0}]
- Trakt API call resulted in an unexpected StatusCode [{0}]
- Failed to read complete http response
AI-assisted analysis of Radarr/Radarr@ca451608dc (2026-08-13).
Data as JSON: /api/errors/86f3f8ba2b37f9a4.
Report an issue: GitHub.