Flow-Launcher/Flow.Launcher · error · SearchException
{e.Message}
Error message
{e.Message} What it means
Thrown as SearchException(engineName, e.Message, e) from SearchManager.SearchAsync when the index/content search IAsyncEnumerable surfaces any exception other than OperationCanceledException or EngineNotAvailableException. It is the catch-all that converts arbitrary provider errors (OLE DB, COM, IO, Everything IPC) into a typed SearchException so the upper layers can render a single failure result. The inner exception is preserved but only its Message is surfaced.
Source
Thrown at Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs:170
continue;
if (IsResultTypeFilteredByActionKeyword(search.Type, actions))
continue;
results.Add(ResultManager.CreateResult(query, search));
}
}
catch (OperationCanceledException)
{
return [.. results];
}
catch (EngineNotAvailableException)
{
throw;
}
catch (Exception e)
{
throw new SearchException(engineName, e.Message, e);
}
results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any(
excludedPath => FilesFolders.PathContains(excludedPath.Path, r.SubTitle, allowEqual: true)));
return [.. results];
}
private List<Result> EverythingContentSearchResult(Query query)
{
return
[
new()
{
Title = Localize.flowlauncher_plugin_everything_enable_content_search(),
SubTitle = Localize.flowlauncher_plugin_everything_enable_content_search_tips(),
IcoPath = "Images/index_error.png",
Action = c =>View on GitHub (pinned to 7fc63b07bb)
Solutions
- Inspect the inner exception (SearchException.InnerException) to find the real cause.
- Make the provider surface EngineNotAvailableException for engine-down cases so they bypass this catch-all.
- Catch SearchException at the result-rendering layer and degrade to a single 'search failed' result instead of crashing.
- Add provider-specific resilience (retry on transient OleDbException, skip-on-error for IOException) so the catch-all is rarely hit.
Example fix
// before
catch (Exception e)
{
throw new SearchException(engineName, e.Message, e);
}
// after - distinguish transient vs fatal and keep partial results
catch (Exception e) when (e is not OperationCanceledException)
{
Main.Context.API.LogException(nameof(SearchManager), $"{engineName} search failed", e);
if (IsTransient(e)) return [.. results];
throw new SearchException(engineName, e.Message, e);
} Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-validate the provider's environment before searching.
if (Settings.IndexSearchEngine == IndexSearchEngineOption.WindowsIndex && !WindowsIndex.WindowsIndex.PathIsIndexed(query.Search))
logger.Info("Query path is not in the Windows Index crawl scope."); Type guard
static bool IsProviderUsable(Settings s) => s.IndexSearchEngine switch {
IndexSearchEngineOption.Everything => File.Exists(s.EverythingInstalledPath),
IndexSearchEngineOption.WindowsIndex => IsWindowsSearchRunning(),
_ => true,
}; Try / catch
try { return await searchManager.SearchAsync(query, token); }
catch (SearchException ex) { App.API.LogException(nameof(SearchManager), $"{ex.EngineName} search failed", ex.InnerException); return new List<Result>(); } Prevention
- Always log SearchException.InnerException, not just Message.
- Have providers throw EngineNotAvailableException for engine-down cases.
- Render a single 'search failed' result instead of crashing the UI.
- Add provider-level resilience (retry, skip-on-error) to keep the catch-all cold.
When it happens
Trigger: IndexProvider.SearchAsync or ContentIndexProvider.ContentSearchAsync throws IOException (drive gone), OleDbException (query parse failure), COMException (shell ext crash), UnauthorizedAccessException (ACL), ObjectDisposedException, or any other runtime exception while enumerating results inside the `await foreach` at line 149.
Common situations: Searching a path on a disconnected network drive; Windows Index returns a malformed row the OleDbDataReader cannot parse; Everything IPC errors mid-stream; a file in the result set triggers an unhandled shell-extension exception; the cancellation token is disposed mid-enumeration producing ObjectDisposedException rather than OperationCanceledException.
Related errors
- {e.Message}
- SHParseDisplayName failed
- SHBindToParent failed
- GetUIObjectOf failed
- InvokeCommand failed with code {hr:X}
AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13).
Data as JSON: /api/errors/de33b7ab0a11d1b6.
Report an issue: GitHub.