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);