diff --git a/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs b/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs
index 7e08fc8d65..2264d226cd 100644
--- a/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs
+++ b/src/System.CommandLine.Suggest.Tests/DotnetSuggestEndToEndTests.cs
@@ -10,12 +10,13 @@
 using static System.Environment;
 using Process = System.CommandLine.Tests.Utility.Process;
 
-namespace System.CommandLine.Suggest.Tests
+namespace System.CommandLine.Suggest.Tests 
 {
     public class DotnetSuggestEndToEndTests : IDisposable
     {
         private readonly ITestOutputHelper _output;
         private readonly FileInfo _endToEndTestApp;
+        private readonly FileInfo _waitAndFailTestApp;
         private readonly FileInfo _dotnetSuggest;
         private readonly (string, string)[] _environmentVariables;
         private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory;
@@ -25,14 +26,15 @@ public DotnetSuggestEndToEndTests(ITestOutputHelper output)
         {
             _output = output;
 
-            // delete sentinel files for EndToEndTestApp in order to trigger registration when it's run
+            // delete sentinel files for TestApps in order to trigger registration when it's run
             var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files"));
 
             if (sentinelsDir.Exists)
             {
-                var sentinels = sentinelsDir.GetFiles("*EndToEndTestApp*");
+                var sentinelsEndToEnd = sentinelsDir.GetFiles("*EndToEndTestApp*");
+                var sentinelsWaitAndFail = sentinelsDir.GetFiles("*WaitAndFailTestApp*");
 
-                foreach (var sentinel in sentinels)
+                foreach (var sentinel in sentinelsEndToEnd.Concat(sentinelsWaitAndFail))
                 {
                     sentinel.Delete();
                 }
@@ -43,12 +45,16 @@ public DotnetSuggestEndToEndTests(ITestOutputHelper output)
                 "TestAssets");
 
             _endToEndTestApp = new DirectoryInfo(currentDirectory)
-                               .GetFiles("EndToEndTestApp".ExecutableName())
-                               .SingleOrDefault();
+                .GetFiles("EndToEndTestApp".ExecutableName())
+                .SingleOrDefault();
 
+            _waitAndFailTestApp = new DirectoryInfo(currentDirectory)
+                .GetFiles("WaitAndFailTestApp".ExecutableName())
+                .SingleOrDefault();
+            
             _dotnetSuggest = new DirectoryInfo(currentDirectory)
-                             .GetFiles("dotnet-suggest".ExecutableName())
-                             .SingleOrDefault();
+                .GetFiles("dotnet-suggest".ExecutableName())
+                .SingleOrDefault();
 
             PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome();
 
@@ -156,5 +162,40 @@ public void Dotnet_suggest_provides_suggestions_for_app_with_only_commandname()
                   .Should()
                   .Be($"--apple{NewLine}--banana{NewLine}--cherry{NewLine}--durian{NewLine}--help{NewLine}--version{NewLine}-?{NewLine}-h{NewLine}/?{NewLine}/h{NewLine}");
         }
+        
+        [ReleaseBuildOnlyFact]
+        public void Dotnet_suggest_fails_to_provide_suggestions_because_app_faulted()
+        {
+            // run "dotnet-suggest register" in explicit way
+            Process.RunToCompletion(
+                _dotnetSuggest.FullName,
+                $"register --command-path \"{_waitAndFailTestApp.FullName}\"",
+                stdOut: s => _output.WriteLine(s),
+                stdErr: s => _output.WriteLine(s),
+                environmentVariables: _environmentVariables).Should().Be(0);
+
+            var stdOut = new StringBuilder();
+            var stdErr = new StringBuilder();
+            
+            var commandLineToComplete = "a";
+            
+            Process.RunToCompletion(
+                _dotnetSuggest.FullName,
+                $"get -e \"{_waitAndFailTestApp.FullName}\" --position {commandLineToComplete.Length} -- \"{commandLineToComplete}\"",
+                stdOut: value => stdOut.AppendLine(value),
+                stdErr: value => stdErr.AppendLine(value),
+                environmentVariables: _environmentVariables);
+            
+            _output.WriteLine($"stdOut:{NewLine}{stdOut}{NewLine}");
+            _output.WriteLine($"stdErr:{NewLine}{stdErr}{NewLine}");
+            
+            stdErr.ToString()
+                .Should()
+                .BeEmpty();
+            
+            stdOut.ToString()
+                .Should()
+                .BeEmpty();
+        }
     }
 }
diff --git a/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj b/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj
index 76add0d5a9..98fa0e21ad 100644
--- a/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj
+++ b/src/System.CommandLine.Suggest.Tests/EndToEndTestApp/EndToEndTestApp.csproj
@@ -6,7 +6,7 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>$(TargetFrameworkForNETSDK)</TargetFramework>
+    <TargetFramework>net8.0</TargetFramework>
   </PropertyGroup>
 
 </Project>
diff --git a/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs b/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs
new file mode 100644
index 0000000000..1f33b50a6e
--- /dev/null
+++ b/src/System.CommandLine.Suggest.Tests/SuggestionStoreTests.cs
@@ -0,0 +1,140 @@
+// Copyright (c) .NET Foundation and contributors. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+using System.CommandLine.Tests.Utility;
+using System.IO;
+using System.Linq;
+using FluentAssertions;
+using Xunit.Abstractions;
+using static System.Environment;
+
+namespace System.CommandLine.Suggest.Tests
+{
+    public class SuggestionStoreTests : IDisposable
+    {
+        protected readonly ITestOutputHelper _output;
+        protected readonly FileInfo _endToEndTestApp;
+        protected readonly FileInfo _waitAndFailTestApp;
+        protected readonly FileInfo _dotnetSuggest;
+        protected readonly (string, string)[] _environmentVariables;
+        private readonly DirectoryInfo _dotnetHostDir = DotnetMuxer.Path.Directory;
+        private static string _testRoot;
+        
+        public SuggestionStoreTests(ITestOutputHelper output)
+        {
+            _output = output;
+
+            // delete sentinel files for TestApps in order to trigger registration when it's run
+            var sentinelsDir = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "system-commandline-sentinel-files"));
+
+            if (sentinelsDir.Exists)
+            {
+                var sentinels = sentinelsDir
+                    .EnumerateFiles()
+                    .Where(f => f.Name.Contains("EndToEndTestApp") || f.Name.Contains("WaitAndFailTestApp"));
+
+                foreach (var sentinel in sentinels)
+                {
+                    sentinel.Delete();
+                }
+            }
+
+            var currentDirectory = Path.Combine(
+                Directory.GetCurrentDirectory(),
+                "TestAssets");
+
+            _endToEndTestApp = new DirectoryInfo(currentDirectory)
+                .GetFiles("EndToEndTestApp".ExecutableName())
+                .SingleOrDefault();
+
+            _waitAndFailTestApp = new DirectoryInfo(currentDirectory)
+                .GetFiles("WaitAndFailTestApp".ExecutableName())
+                .SingleOrDefault();
+            
+            _dotnetSuggest = new DirectoryInfo(currentDirectory)
+                .GetFiles("dotnet-suggest".ExecutableName())
+                .SingleOrDefault();
+
+            PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome();
+
+            _environmentVariables = new[] {
+                ("DOTNET_ROOT", _dotnetHostDir.FullName),
+                ("INTERNAL_TEST_DOTNET_SUGGEST_HOME", _testRoot)};
+        }
+
+        public void Dispose()
+        {
+            if (_testRoot != null && Directory.Exists(_testRoot))
+            {
+                Directory.Delete(_testRoot, recursive: true);
+            }
+        }
+
+        private static void PrepareTestHomeDirectoryToAvoidPolluteBuildMachineHome()
+        {
+            _testRoot = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
+            Directory.CreateDirectory(_testRoot);
+        }
+        
+        [ReleaseBuildOnlyFact]
+        public void GetCompletions_obtains_suggestions_successfully()
+        {
+            // run "dotnet-suggest register" in explicit way
+            Process.RunToCompletion(
+                _dotnetSuggest.FullName,
+                $"register --command-path \"{_endToEndTestApp.FullName}\"",
+                stdOut: s => _output.WriteLine(s),
+                stdErr: s => _output.WriteLine(s),
+                environmentVariables: _environmentVariables).Should().Be(0);
+            
+            var store = new SuggestionStore();
+            var completions = store.GetCompletions(_endToEndTestApp.FullName, "[suggest:1] \"a\"", TimeSpan.FromSeconds(1));
+            completions.Should().Be($"--apple{NewLine}--banana{NewLine}--durian{NewLine}");
+        }
+        
+        [ReleaseBuildOnlyFact]
+        public void GetCompletions_fails_to_obtain_suggestions_because_app_takes_too_long()
+        {
+            var store = new SuggestionStore();
+            var appHangingTimeSpanArgument = TimeSpan.FromMilliseconds(2000).ToString();
+            var completions = store
+                .GetCompletions(_waitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000));
+            completions.Should().BeEmpty();
+        }
+        
+        [ReleaseBuildOnlyFact]
+        public void GetCompletions_fails_to_obtain_suggestions_because_app_exited_with_nonzero_code()
+        {
+            var store = new SuggestionStore();
+            var appHangingTimeSpanArgument = TimeSpan.FromMilliseconds(0).ToString();
+            var completions = store
+                .GetCompletions(_waitAndFailTestApp.FullName, appHangingTimeSpanArgument, TimeSpan.FromMilliseconds(1000));
+            completions.Should().BeEmpty();
+        }
+        
+        [ReleaseBuildOnlyFact]
+        public void GetCompletions_throws_when_exeFileName_is_null()
+        {
+            var store = new SuggestionStore();
+            var act = () => store.GetCompletions(null, "[suggest:1] \"a\"", TimeSpan.FromSeconds(1));
+            act.Should().Throw<ArgumentException>();
+        }
+        
+        [ReleaseBuildOnlyFact]
+        public void GetCompletions_throws_when_exeFileName_is_empty()
+        {
+            var store = new SuggestionStore();
+            var act = () => store.GetCompletions("   ", "[suggest:1] \"a\"", TimeSpan.FromSeconds(1));
+            act.Should().Throw<ArgumentException>();
+        }
+        
+        [ReleaseBuildOnlyFact]
+        public void GetCompletions_throws_when_exeFile_does_not_exist()
+        {
+            var store = new SuggestionStore();
+            var act = () => store
+                .GetCompletions("thisExecutableDoesNotExist.exe", "[suggest:1] \"a\"", TimeSpan.FromSeconds(1));
+            act.Should().Throw<ArgumentException>();
+        }
+    }
+}
diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs
new file mode 100644
index 0000000000..d1d22b38ab
--- /dev/null
+++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/Program.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Threading.Tasks;
+
+namespace WaitAndFailTestApp;
+
+public class Program
+{
+    private static TimeSpan defaultWait = TimeSpan.FromMilliseconds(3000);
+    
+    //we should not be able to receive any suggestion from this test app,
+    //so we are not constructing it using CliConfiguration
+    
+    static async Task Main(string[] args)
+    {
+        var waitPeriod = args.Length > 0 && int.TryParse(args[0], out var millisecondsToWaitParsed)
+            ? TimeSpan.FromMilliseconds(millisecondsToWaitParsed)
+            : defaultWait; 
+        
+        await Task.Delay(waitPeriod);
+        Environment.ExitCode = 1;
+        
+        Console.WriteLine("this 'suggestion' is provided too late and/or with invalid app exit code");
+    }
+}
+
diff --git a/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj
new file mode 100644
index 0000000000..98fa0e21ad
--- /dev/null
+++ b/src/System.CommandLine.Suggest.Tests/WaitAndFailTestApp/WaitAndFailTestApp.csproj
@@ -0,0 +1,12 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\System.CommandLine\System.CommandLine.csproj" />
+  </ItemGroup>
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net8.0</TargetFramework>
+  </PropertyGroup>
+
+</Project>
diff --git a/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj b/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj
index 76540b1a7a..4a314f6eae 100644
--- a/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj
+++ b/src/System.CommandLine.Suggest.Tests/dotnet-suggest.Tests.csproj
@@ -2,9 +2,25 @@
 
   <PropertyGroup>
     <TargetFramework>$(TargetFrameworkForNETSDK)</TargetFramework>
-    <DefaultExcludesInProjectFolder>$(DefaultExcludesInProjectFolder);EndToEndTestApp\**</DefaultExcludesInProjectFolder>
+    <DefaultExcludesInProjectFolder>$(DefaultExcludesInProjectFolder);EndToEndTestApp\**;WaitAndFailTestApp\**</DefaultExcludesInProjectFolder>
   </PropertyGroup>
 
+  <ItemGroup>
+    <Compile Remove="TestResults\**" />
+    <EmbeddedResource Remove="TestResults\**" />
+    <None Remove="TestResults\**" />
+    
+    <Compile Remove="EndToEndTestApp/**" />
+    <Content Remove="EndToEndTestApp/**" />
+    <EmbeddedResource Remove="EndToEndTestApp/**" />
+    <None Remove="EndToEndTestApp/**" />
+
+    <Compile Remove="WaitAndFailTestApp/**" />
+    <Content Remove="WaitAndFailTestApp/**" />
+    <EmbeddedResource Remove="WaitAndFailTestApp/**" />
+    <None Remove="WaitAndFailTestApp/**" />
+  </ItemGroup>
+
   <ItemGroup>
     <Compile Include="..\System.CommandLine.Suggest\DotnetMuxer.cs" Link="DotnetMuxer.cs" />
   </ItemGroup>
@@ -42,6 +58,10 @@
     <MSBuild BuildInParallel="False" Projects="EndToEndTestApp/EndToEndTestApp.csproj" Targets="Restore" Properties="UseAppHost=true;SelfContained=false;RuntimeIdentifier=$(Rid);ForceRestoreToEvaluateSeparately=1;Configuration=Release" />
 
     <MSBuild BuildInParallel="False" Projects="EndToEndTestApp/EndToEndTestApp.csproj" Targets="Build;Publish" Properties="UseAppHost=true;SelfContained=false;RuntimeIdentifier=$(Rid);PublishDir=$(TestAssetsPath);Configuration=Release" />
+
+    <MSBuild BuildInParallel="False" Projects="WaitAndFailTestApp/WaitAndFailTestApp.csproj" Targets="Restore" Properties="UseAppHost=true;SelfContained=false;RuntimeIdentifier=$(Rid);ForceRestoreToEvaluateSeparately=1;Configuration=Release" />
+    
+    <MSBuild BuildInParallel="False" Projects="WaitAndFailTestApp/WaitAndFailTestApp.csproj" Targets="Build;Publish" Properties="UseAppHost=true;SelfContained=false;RuntimeIdentifier=$(Rid);PublishDir=$(TestAssetsPath);Configuration=Release" />
   </Target>
 
 </Project>
diff --git a/src/System.CommandLine.Suggest/SuggestionStore.cs b/src/System.CommandLine.Suggest/SuggestionStore.cs
index ac93972eb1..9e41b44402 100644
--- a/src/System.CommandLine.Suggest/SuggestionStore.cs
+++ b/src/System.CommandLine.Suggest/SuggestionStore.cs
@@ -4,6 +4,7 @@
 using System.ComponentModel;
 using System.Diagnostics;
 using System.IO;
+using System.Text;
 using System.Threading.Tasks;
 
 namespace System.CommandLine.Suggest
@@ -37,19 +38,31 @@ public string GetCompletions(string exeFileName, string suggestionTargetArgument
 
                 using (var process = new Process
                                      {
-                                         StartInfo = processStartInfo
+                                         StartInfo = processStartInfo,
                                      })
                 {
+                    
                     process.Start();
-
-                    Task<string> readToEndTask = process.StandardOutput.ReadToEndAsync();
-
-                    if (readToEndTask.Wait(timeout))
+                    
+                    var stringBuilder = new StringBuilder();
+                    process.OutputDataReceived += (sender, eventArgs) =>
+                    {
+                        if (eventArgs.Data != null)
+                        {
+                            stringBuilder.AppendLine(eventArgs.Data);
+                        }
+                    };
+                    process.BeginOutputReadLine();
+                    if (process.WaitForExit(timeout) && process.ExitCode == 0)
                     {
-                        result = readToEndTask.Result;
+                        process.CancelOutputRead();
+                        result = stringBuilder.ToString();
                     }
                     else
                     {
+#if DEBUG
+                    Program.LogDebug($"Killing the process after a timeout. Process exit code: {process.ExitCode}");
+#endif
                         process.Kill();
                     }
                 }