Skip to content
Merged
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions src/Sentry/Internal/MainExceptionProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,9 @@ private static Mechanism GetMechanism(Exception exception, int id, int? parentId
exception.Data.Remove(Mechanism.DescriptionKey);
}

// Add HResult to mechanism data before adding exception data, so that it can be overridden.
mechanism.Data["HResult"] = $"0x{exception.HResult:X8}";
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a test too please?

We have tests already which you base off of:

public void Process_ExceptionsWithoutData_MechanismDataIsEmpty()
{
var sut = _fixture.GetSut();
var evt = new SentryEvent();
var ex = GetHandledException();
sut.Process(ex, evt);
var sentryException = evt.SentryExceptions!.Single();
Assert.Empty(sentryException.Mechanism!.Data);
}

Copy link
Member

Choose a reason for hiding this comment

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

Oh one more note: https://learn.microsoft.com/en-us/dotnet/api/system.exception.hresult?view=net-9.0

How about we don't add the property if HResult is not default?

Otherwise we'll be getting HResult: 0 for lots of stuff

Copy link

@whiskhub whiskhub Mar 8, 2025

Choose a reason for hiding this comment

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

The chance for HResult being 0 in an exception is effectively 0 😅 because 0 means S_OK, so success.
The default HResult in C# is 0x80131500 COR_E_EXCEPTION.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, unless someone manually change the HResult to 0, the value will always be like 0x800... . Every .NET BCL Exception have different default HResult.

So we can assume 0 is also meaningful that something is going wrong here (Deliberately set by developer or library author, although almost no one will do so).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could you add a test too please?

Not familiar about that, maybe someone else can help?

Copy link
Contributor Author

@Lightczx Lightczx Mar 10, 2025

Choose a reason for hiding this comment

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

-2146233088 is 0x80131500 which is COR_E_EXCEPTION

https://github.com/dotnet/runtime/blob/d17420560540e4184a78f431de8341f747068c4f/src/coreclr/pal/prebuilt/inc/corerror.h#L227

If a Exception is throw by BCL, then it may or may not be mapped/wrapped.
Especially for HttpRequestException, if the inner exception is IOException, the HResult is different from which inner exception is SocketException

Choose a reason for hiding this comment

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

I would avoid adding any filtering here. Any HResult value may give some information. I don‘t think it will confuse anyone, since already today the HResult value can be seen on any exception in the debugger.

Choose a reason for hiding this comment

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

I've written a short test. Feel free to commit it:

[Fact]
public void Process_ExceptionWithHResult_MechanismDataIsPopulated()
{
	var sut = _fixture.GetSut();
	var evt = new SentryEvent();
	const int RPC_E_WRONG_THREAD = -2147417842;
	const string RPC_E_WRONG_THREAD_MSG = "The application called an interface that was marshalled for a different thread.";
	var ex = new System.Runtime.InteropServices.COMException(RPC_E_WRONG_THREAD_MSG, RPC_E_WRONG_THREAD);

	sut.Process(ex, evt);

	var sentryException = evt.SentryExceptions!.Single();
	var data = sentryException.Mechanism!.Data;

	Assert.Contains(data, pair => pair.Key == "HResult" && pair.Value.Equals("0x8001010E"));
}

Copy link
Contributor

Choose a reason for hiding this comment

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

-2146233088 is 0x80131500 which is COR_E_EXCEPTION
https://github.com/dotnet/runtime/blob/d17420560540e4184a78f431de8341f747068c4f/src/coreclr/pal/prebuilt/inc/corerror.h#L227

@bruno-garcia does it make sense to pull that mapping into the issues details page?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

pull that mapping into the issues details page

Not quite, that's not the full set of the HRESULT, and COM/WinRT/Win32 components can have custom values.


// Copy remaining exception data to mechanism data.
foreach (var key in exception.Data.Keys.OfType<string>())
{
Expand Down
Loading