Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,18 @@ private void ProcessRequests(ITestRequestManager testRequestManager)
catch (Exception ex)
{
EqtTrace.Error("DesignModeClient: Error processing request: {0}", ex);

// Notify the caller (IDE) about the error so it does not hang
// waiting for a response that will never come.
try
{
_communicationManager.SendMessage(MessageType.ProtocolError, ex.Message);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using ex.Message alone can be empty and loses the exception type/context, which makes the ProtocolError less actionable for the IDE/user. Consider including at least the exception type + message (e.g., ${ex.GetType().FullName}: ${ex.Message}) or a structured error payload, while being mindful of not sending overly large data (stack traces) over the protocol unless explicitly desired.

Suggested change
_communicationManager.SendMessage(MessageType.ProtocolError, ex.Message);
_communicationManager.SendMessage(
MessageType.ProtocolError,
string.Format(
CultureInfo.InvariantCulture,
"{0}: {1}",
ex.GetType().FullName,
ex.Message));

Copilot uses AI. Check for mistakes.
}
catch (Exception sendEx)
{
EqtTrace.Error("DesignModeClient: Failed to send ProtocolError to client: {0}", sendEx);
}
Comment on lines +295 to +304
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This introduces a repeated pattern (log error → try send ProtocolError → log send failure). Since similar logic now exists on both sides (testhost + vstest.console), consider extracting a small helper (per component) like TrySendProtocolError(Exception ex) to keep exception paths consistent and reduce future drift (e.g., message formatting, telemetry, or fallback behavior).

Copilot uses AI. Check for mistakes.

Stop();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,32 @@ public bool AttachDebuggerToProcess(AttachDebuggerInfo attachDebuggerInfo)
}

public void OnMessageReceived(object? sender, MessageReceivedEventArgs messageReceivedArgs)
{
try
{
OnMessageReceivedCore(messageReceivedArgs);
}
catch (Exception ex)
{
EqtTrace.Error("TestRequestHandler.OnMessageReceived: Failed to process message, sending ProtocolError and closing session: {0}", ex);

// Notify the caller about the error so it does not hang
// waiting for a response that will never come.
try
{
SendData(_dataSerializer.SerializePayload(MessageType.ProtocolError, ex.Message));
}
catch (Exception sendEx)
{
EqtTrace.Error("TestRequestHandler.OnMessageReceived: Failed to send ProtocolError: {0}", sendEx);
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description calls out failures due to missing System.Text.Json dependencies during deserialization. In that failure mode, _dataSerializer.SerializePayload(...) is likely to fail for the same reason, which would prevent ProtocolError from being sent and can reintroduce the hang. Consider a fallback error-notification path that does not depend on the JSON serializer (e.g., sending a minimal pre-serialized frame / raw transport-level error message if supported), or ensure the communication layer can emit ProtocolError even when payload serialization fails.

Suggested change
EqtTrace.Error("TestRequestHandler.OnMessageReceived: Failed to send ProtocolError: {0}", sendEx);
EqtTrace.Error("TestRequestHandler.OnMessageReceived: Failed to send ProtocolError using serializer: {0}", sendEx);
// Fallback: attempt to send a minimal, serializer-independent error message
try
{
var fallbackMessage = "ProtocolError: " + ex.ToString();
EqtTrace.Verbose("TestRequestHandler.OnMessageReceived: Sending fallback ProtocolError message without serializer: {0}", fallbackMessage);
SendData(fallbackMessage);
}
catch (Exception fallbackEx)
{
EqtTrace.Error("TestRequestHandler.OnMessageReceived: Failed to send fallback ProtocolError message: {0}", fallbackEx);
}

Copilot uses AI. Check for mistakes.
}

_sessionCompleted.Set();
Close();
}
}

private void OnMessageReceivedCore(MessageReceivedEventArgs messageReceivedArgs)
{
var message = _dataSerializer.DeserializeMessage(messageReceivedArgs.Data!);
EqtTrace.Info("TestRequestHandler.OnMessageReceived: received message: {0}", message);
Expand Down
Loading