diff --git a/frontend/src/InteractiveSearch/InteractiveSearch.js b/frontend/src/InteractiveSearch/InteractiveSearch.js index 74d2fc219..88af239f2 100644 --- a/frontend/src/InteractiveSearch/InteractiveSearch.js +++ b/frontend/src/InteractiveSearch/InteractiveSearch.js @@ -1,5 +1,6 @@ import PropTypes from 'prop-types'; -import React from 'react'; +import React, { Fragment } from 'react'; +import getErrorMessage from 'Utilities/Object/getErrorMessage'; import { align, icons, sortDirections } from 'Helpers/Props'; import LoadingIndicator from 'Components/Loading/LoadingIndicator'; import Icon from 'Components/Icon'; @@ -109,6 +110,8 @@ function InteractiveSearch(props) { onGrabPress } = props; + const errorMessage = getErrorMessage(error); + return (
@@ -125,33 +128,42 @@ function InteractiveSearch(props) {
{ - isFetching && - + isFetching ? : null } { - !isFetching && !!error && + !isFetching && error ?
- Unable to load results for this episode search. Try again later -
+ { + errorMessage ? + + Search failed because its {errorMessage.charAt(0).toLowerCase() + errorMessage.slice(1)}. + Try refreshing the series info and verify the necessary information is present before searching again + : + 'Unable to load results for this episode search. Try again later' + } +
: + null } { - !isFetching && isPopulated && !totalReleasesCount && + !isFetching && isPopulated && !totalReleasesCount ?
No results found -
+ : + null } { - !!totalReleasesCount && isPopulated && !items.length && + !!totalReleasesCount && isPopulated && !items.length ?
All results are hidden by the applied filter -
+ : + null } { - isPopulated && !!items.length && + isPopulated && !!items.length ? -
+ : + null } { - totalReleasesCount !== items.length && !!items.length && + totalReleasesCount !== items.length && !!items.length ?
Some results are hidden by the applied filter -
+ : + null } ); diff --git a/src/NzbDrone.Core/Exceptions/SearchFailedException.cs b/src/NzbDrone.Core/Exceptions/SearchFailedException.cs new file mode 100644 index 000000000..e5f42595c --- /dev/null +++ b/src/NzbDrone.Core/Exceptions/SearchFailedException.cs @@ -0,0 +1,11 @@ +using NzbDrone.Common.Exceptions; + +namespace NzbDrone.Core.Exceptions +{ + public class SearchFailedException : NzbDroneException + { + public SearchFailedException(string message) : base(message) + { + } + } +} diff --git a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs index 6b6f79e2e..520324956 100644 --- a/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs +++ b/src/NzbDrone.Core/IndexerSearch/NzbSearchService.cs @@ -13,6 +13,7 @@ using NzbDrone.Core.Tv; using System.Linq; using NzbDrone.Common.TPL; using NzbDrone.Common.Extensions; +using NzbDrone.Core.Exceptions; namespace NzbDrone.Core.IndexerSearch { @@ -62,7 +63,8 @@ namespace NzbDrone.Core.IndexerSearch { if (string.IsNullOrWhiteSpace(episode.AirDate)) { - throw new InvalidOperationException("Daily episode is missing AirDate. Try to refresh series info."); + _logger.Error("Daily episode is missing an air date. Try refreshing the series info."); + throw new SearchFailedException("Air date is missing"); } return SearchDaily(series, episode, userInvokedSearch, interactiveSearch); @@ -205,7 +207,8 @@ namespace NzbDrone.Core.IndexerSearch } else { - throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", $"Can not search for {series.Title} - S{episode.SeasonNumber:00}E{episode.EpisodeNumber:00} it does not have an absolute episode number"); + _logger.Error($"Can not search for {series.Title} - S{episode.SeasonNumber:00}E{episode.EpisodeNumber:00} it does not have an absolute episode number"); + throw new SearchFailedException("Absolute episode number is missing"); } return Dispatch(indexer => indexer.Fetch(searchSpec), searchSpec); diff --git a/src/NzbDrone.Core/NzbDrone.Core.csproj b/src/NzbDrone.Core/NzbDrone.Core.csproj index 6aff86839..4eab897b5 100644 --- a/src/NzbDrone.Core/NzbDrone.Core.csproj +++ b/src/NzbDrone.Core/NzbDrone.Core.csproj @@ -146,6 +146,7 @@ + diff --git a/src/Sonarr.Api.V3/Indexers/ReleaseModule.cs b/src/Sonarr.Api.V3/Indexers/ReleaseModule.cs index a52f37730..a0d803c77 100644 --- a/src/Sonarr.Api.V3/Indexers/ReleaseModule.cs +++ b/src/Sonarr.Api.V3/Indexers/ReleaseModule.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using FluentValidation; using Nancy; -using Nancy.ModelBinding; using NLog; using NzbDrone.Common.Cache; using NzbDrone.Common.Extensions; @@ -110,7 +108,7 @@ namespace Sonarr.Api.V3.Indexers } catch (ReleaseDownloadException ex) { - _logger.ErrorException(ex.Message, ex); + _logger.Error(ex, ex.Message); throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed"); } @@ -141,6 +139,10 @@ namespace Sonarr.Api.V3.Indexers return MapDecisions(prioritizedDecisions); } + catch (SearchFailedException ex) + { + throw new NzbDroneClientException(HttpStatusCode.BadRequest, ex.Message); + } catch (Exception ex) { _logger.Error(ex, "Episode search failed: " + ex.Message); @@ -158,6 +160,10 @@ namespace Sonarr.Api.V3.Indexers return MapDecisions(prioritizedDecisions); } + catch (SearchFailedException ex) + { + throw new NzbDroneClientException(HttpStatusCode.BadRequest, ex.Message); + } catch (Exception ex) { _logger.Error(ex, "Season search failed: " + ex.Message);