{"record":{"id":"de33b7ab0a11d1b6","repo":"Flow-Launcher/Flow.Launcher","slug":"e-message","errorCode":null,"errorMessage":"{e.Message}","messagePattern":"\\{e\\.Message\\}","errorType":"exception","errorClass":"SearchException","httpStatus":null,"severity":"error","filePath":"Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs","lineNumber":170,"sourceCode":"                        continue;\n\n                    if (IsResultTypeFilteredByActionKeyword(search.Type, actions))\n                        continue;\n\n                    results.Add(ResultManager.CreateResult(query, search));\n                }\n            }\n            catch (OperationCanceledException)\n            {\n                return [.. results];\n            }\n            catch (EngineNotAvailableException)\n            {\n                throw;\n            }\n            catch (Exception e)\n            {\n                throw new SearchException(engineName, e.Message, e);\n            }\n\n            results.RemoveWhere(r => Settings.IndexSearchExcludedSubdirectoryPaths.Any(\n                excludedPath => FilesFolders.PathContains(excludedPath.Path, r.SubTitle, allowEqual: true)));\n\n            return [.. results];\n        }\n\n        private List<Result> EverythingContentSearchResult(Query query)\n        {\n            return\n            [\n                new()\n                {\n                    Title = Localize.flowlauncher_plugin_everything_enable_content_search(),\n                    SubTitle = Localize.flowlauncher_plugin_everything_enable_content_search_tips(),\n                    IcoPath = \"Images/index_error.png\",\n                    Action = c =>","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/Flow-Launcher/Flow.Launcher/blob/7fc63b07bbaa10a0f0b2601487913fcba9ed24b0/Plugins/Flow.Launcher.Plugin.Explorer/Search/SearchManager.cs#L152-L188","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\ncatch (Exception e)\n{\n    throw new SearchException(engineName, e.Message, e);\n}\n\n// after - distinguish transient vs fatal and keep partial results\ncatch (Exception e) when (e is not OperationCanceledException)\n{\n    Main.Context.API.LogException(nameof(SearchManager), $\"{engineName} search failed\", e);\n    if (IsTransient(e)) return [.. results];\n    throw new SearchException(engineName, e.Message, e);\n}","handlingStrategy":"try-catch","validationCode":"// Pre-validate the provider's environment before searching.\nif (Settings.IndexSearchEngine == IndexSearchEngineOption.WindowsIndex && !WindowsIndex.WindowsIndex.PathIsIndexed(query.Search))\n    logger.Info(\"Query path is not in the Windows Index crawl scope.\");","typeGuard":"static bool IsProviderUsable(Settings s) => s.IndexSearchEngine switch {\n    IndexSearchEngineOption.Everything => File.Exists(s.EverythingInstalledPath),\n    IndexSearchEngineOption.WindowsIndex => IsWindowsSearchRunning(),\n    _ => true,\n};","tryCatchPattern":"try { return await searchManager.SearchAsync(query, token); }\ncatch (SearchException ex) { App.API.LogException(nameof(SearchManager), $\"{ex.EngineName} search failed\", ex.InnerException); return new List<Result>(); }","preventionTips":["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."],"tags":["search-manager","search-exception","catch-all","async-enumerable","csharp"],"backgroundTag":null,"analyzedSha":"7fc63b07bbaa10a0f0b2601487913fcba9ed24b0","analyzedAt":"2026-08-13T14:54:20.914Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}