From 71032f797d94749fbedd5694d5a36fb559b7a864 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Thu, 26 Feb 2026 16:18:02 +0100 Subject: [PATCH 1/2] Use innermost exception message for ErrorMessage to surface root cause errors When HttpClient wraps errors (e.g. TLS/SSL failures), the outer exception message is generic ("An error occurred while sending the request"). Using GetBaseException().Message surfaces the actual root cause, making diagnostics much easier. The full exception chain remains preserved in ErrorException. Fixes #2278 Co-Authored-By: Claude Opus 4.6 --- src/RestSharp/Response/RestResponseBase.cs | 2 +- src/RestSharp/RestClient.Async.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RestSharp/Response/RestResponseBase.cs b/src/RestSharp/Response/RestResponseBase.cs index b54ed4e17..57b1f5c4a 100644 --- a/src/RestSharp/Response/RestResponseBase.cs +++ b/src/RestSharp/Response/RestResponseBase.cs @@ -161,6 +161,6 @@ protected RestResponseBase(RestRequest request) { internal void AddException(Exception exception) { ErrorException = exception; - ErrorMessage = exception.Message; + ErrorMessage = exception.GetBaseException().Message; } } diff --git a/src/RestSharp/RestClient.Async.cs b/src/RestSharp/RestClient.Async.cs index da807a542..3e6a83d6f 100644 --- a/src/RestSharp/RestClient.Async.cs +++ b/src/RestSharp/RestClient.Async.cs @@ -65,7 +65,7 @@ static RestResponse GetErrorResponse(RestRequest request, Exception exception, C ResponseStatus = exception is OperationCanceledException ? TimedOut() ? ResponseStatus.TimedOut : ResponseStatus.Aborted : ResponseStatus.Error, - ErrorMessage = exception.Message, + ErrorMessage = exception.GetBaseException().Message, ErrorException = exception }; From 5b1de23034bed21659ec964150b888281bc63c08 Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Thu, 26 Feb 2026 16:24:20 +0100 Subject: [PATCH 2/2] Add tests verifying ErrorMessage surfaces innermost exception message Co-Authored-By: Claude Opus 4.6 --- test/RestSharp.Tests/ErrorMessageTests.cs | 43 +++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 test/RestSharp.Tests/ErrorMessageTests.cs diff --git a/test/RestSharp.Tests/ErrorMessageTests.cs b/test/RestSharp.Tests/ErrorMessageTests.cs new file mode 100644 index 000000000..811f23445 --- /dev/null +++ b/test/RestSharp.Tests/ErrorMessageTests.cs @@ -0,0 +1,43 @@ +using System.Security.Authentication; + +namespace RestSharp.Tests; + +public class ErrorMessageTests { + [Fact] + public async Task ErrorMessage_surfaces_innermost_exception_message() { + const string innerMessage = "The remote certificate is invalid according to the validation procedure."; + + var innerException = new AuthenticationException(innerMessage); + var wrappedException = new HttpRequestException("An error occurred while sending the request.", innerException); + + var handler = new FakeHandler(wrappedException); + var client = new RestClient(new RestClientOptions("https://dummy.org") { ConfigureMessageHandler = _ => handler }); + + var response = await client.ExecuteAsync(new RestRequest("/")); + + response.ErrorMessage.Should().Be(innerMessage); + response.ErrorException.Should().BeOfType(); + response.ErrorException!.InnerException.Should().BeOfType(); + response.ResponseStatus.Should().Be(ResponseStatus.Error); + } + + [Fact] + public async Task ErrorMessage_uses_direct_message_when_no_inner_exception() { + const string message = "No such host is known."; + + var exception = new HttpRequestException(message); + var handler = new FakeHandler(exception); + var client = new RestClient(new RestClientOptions("https://dummy.org") { ConfigureMessageHandler = _ => handler }); + + var response = await client.ExecuteAsync(new RestRequest("/")); + + response.ErrorMessage.Should().Be(message); + response.ErrorException.Should().BeOfType(); + response.ErrorException!.InnerException.Should().BeNull(); + } + + class FakeHandler(Exception exception) : HttpMessageHandler { + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + => throw exception; + } +}