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.

Solutions

  1. Inspect the inner exception (SearchException.InnerException) to find the real cause.
  2. Make the provider surface EngineNotAvailableException for engine-down cases so they bypass this catch-all.
  3. Catch SearchException at the result-rendering layer and degrade to a single 'search failed' result instead of crashing.
  4. 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

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


AI-assisted analysis of Flow-Launcher/Flow.Launcher@7fc63b07bb (2026-08-13). Data as JSON: /api/errors/de33b7ab0a11d1b6. Report an issue: GitHub.

Appendix: 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)