.NET C# - does not report to the backend

I have just implemented Sentry in my .NET application.

When I run it from a console application it works fine and it reports back as expected to the backend.

However, when I use the exact same code in another code project (which is an add-in to 3rd party application) it doesn’t report back and in the stacktrace I can see the following:

Debug: Envelope 2d383d1960054456b0cc9e40ead76c5a handed off to transport. #1 in queue.
** Fatal: Exception in the background worker.**
System.FormatException: Index (zero based) must be greater than or equal to zero and less than the size of the argument list.
** at System.Text.StringBuilder.AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)**
** at System.String.FormatHelper(IFormatProvider provider, String format, ParamsArray args)**
** at System.String.Format(String format, Object args)**
** at Sentry.Infrastructure.TraceDiagnosticLogger.Log(SentryLevel logLevel, String message, Exception exception, Object args)**
** at Sentry.Extensibility.DiagnosticLoggerExtensions.LogError[TArg,TArg2](IDiagnosticLogger logger, String message, Exception exception, TArg arg, TArg2 arg2)**
** at Sentry.Internal.BackgroundWorker.d__19.MoveNext()**

My code is:
using (SentrySdk.Init(o =>
{
o.Dsn = “MYDNSVALUE”;
o.SendDefaultPii = true;
o.TracesSampleRate = 1.0;
o.Release = “2.0”;
o.SampleRate = 1;
o.Debug = true;
o.AutoSessionTracking = false;
o.DiagnosticLogger = new TraceDiagnosticLogger(SentryLevel.Debug);
}))
{
try
{
throw new Exception();
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
}
}

Any help/advice would be great.
Thanks

Hello @dotNetDev
This bug was fixed in the latest release v3.6.1: NuGet Gallery | Sentry 3.6.1
Can you try it and see if it works?

1 Like

Thanks, I just installed 3.6.1 and it now shows another error:

System.Net.Http.HttpRequestException: Error while copying content to a stream. —> System.IO.FileNotFoundException: Could not load file or assembly ‘System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies. The system cannot find the file specified.
at System.Threading.Tasks.ValueTask.get_IsCompleted()

I have got a reference to “System.Runtime.CompilerServices.Unsafe” in the project but it is version “5.0.0.0”. I uninstalled this and then tried to install version 4,5,3 (which apparently is 4.0.4.1) but then it tries to install an old version of Sentry.

What am I missing here?
Thanks

What version of .NET Framework are you targeting? Does this break with 4.7.1 or later?
Targeting .NET Framework 4.6.1 has some dependency resolution issue that were resolved in later version of .NET Framework, so I wonder if this is something targeting 4.7.1 resolves.

We don’t depend on System.Runtime.CompilerServices.Unsafe but it’s a transient dependency. Not sure what’s failing here.

System.Threading.Tasks.Extensions depends on it on version 4.5.3
And System.Memory also on the same version (or higher)

System.Text.Json though seems to depend on it by on version 5.0.0 or higher.

Do you have some binding redirect rules defined? .NET Framework should just resolve to 5.0,0 and things should just work.

So we are using .NET Framework 4.8 in the project.

Very strange as it works from a simple console application but not in the project where we need to use it.

Our app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.InteropServices.RuntimeInformation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Sentry" publicKeyToken="fba2ec45388e2af0" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-3.6.1.0" newVersion="3.6.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-5.0.0.2" newVersion="5.0.0.2" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
  </startup>
</configuration>

The binding redirects look correct.
Sounds like you have another dependency that requires System.Runtime.CompilerServices.Unsafe on a version older than 5.0.0?

Unable to uninstall ‘System.Runtime.CompilerServices.Unsafe.5.0.0’ because ‘System.Memory.4.5.4, System.Text.Json.5.0.2, System.Threading.Tasks.Extensions.4.5.4’ depend on it.

The strange thing is that I get the error
(“System.Net.Http.HttpRequestException: Error while copying content to a stream. —> System.IO.FileNotFoundException: Could not load file or assembly ‘System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral,”)
at the point where it is trying to send the request to Sentry backend. So I have no idea why it is trying to load it at that point?

@dotNetDev Can you open your console project (where Sentry works) and try adding all of the dependencies from your current project. Does it work? Make sure both the console project and the main project use the same target framework and same project format (i.e. legacy csproj vs SDK csproj). This should help at least isolate what is causing the binding conflict.

This doesn’t sound too strange to me. When did you expect it to load?

I have now added/referenced the same dependencies in to the console app project. They are both the same type of project and the same .NET version (4.8). It still works in the console app. So I am not sure what is going on in that project to be honest.

I guess what I don’t understand is what is going on under the hood. It finds the Sentry dll fine as it is pulling everything together so it is just the send bit that doesn’t work. So I guess it is using the that missing dll at that point? Or is trying to pull together information about all referenced dll-s as part of the request?

All we want is to simply send up exceptions to your backend - is there a way we can send HTTP requests (building up the requests manually)?

It sounds like there’s something particular about your project. You mentioned it was an add-in to a 3rd party application, could it be that the application does not read/respect the binding redirects file? If it’s loading the assembly dynamically, I imagine it can very well be the case. Can you create a minimal add-in project and try adding only Sentry there and see if it works without any other dependencies/packages?

The DLLs are loaded dynamically (hence the ‘D’) at runtime when they are needed. Evidently, System.Runtime.CompilerServices.Unsafe assembly is not needed until Sentry attempts to send an event, so that’s when the exception happens. It’s possible to force-load all assemblies eagerly by probing them with reflection, which would result in an exception being thrown earlier.

All we want is to simply send up exceptions to your backend - is there a way we can send HTTP requests (building up the requests manually)?

Yes, you will want to start here, probably: https://develop.sentry.dev/sdk/envelopes/

I’m having the same issue too, but on .NET 4.6.2 (in a Win Forms app) & 3.6.1. I am totally out of ideas. No issues raising a message or exception, it seems to only happen when the message in the queue is being dispatched, which seems to be done in a background thread.

My code is basically the same as the code in @dotNetDev’s example. I have binding redirects matching too.

The debug window shows this:

Debug: Envelope fe912efd24bd45f78641d13a8749f40a handed off to transport. #1 in queue.
Error: Error while processing envelope (event ID: ‘fe912efd24bd45f78641d13a8749f40a’). #1 in queue.
System.Net.Http.HttpRequestException: Error while copying content to a stream. —> System.IO.FileLoadException: Could not load file or assembly ‘System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
at System.Threading.Tasks.ValueTask.get_IsCompleted()
at Sentry.Protocol.Envelopes.Envelope.d__9.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Sentry.Protocol.Envelopes.Envelope.d__10.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Sentry.Internal.Http.EnvelopeHttpContent.d__2.MoveNext()
— End of inner exception stack trace —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Sentry.Internal.Http.GzipBufferedRequestBodyHandler.d__3.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Sentry.Internal.Http.RetryAfterHandler.d__7.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Sentry.Internal.Http.HttpTransport.d__13.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()

My project has no references to System.Runtime.Compiler.Unsafe and I can’t see the assembly being loaded at any point dynamically or otherwise.

Any ideas?

Thanks :slight_smile:

I have now created a new very simple add-in project with minimal other dependencies and it still fails with the same error. So it could be the way that the 3rd party application loads in the assemblies but we are using other external dll-s and they all work fine.
Also, as someone else now reported the same issue I suspect it might not be.

I’m also having a similar problem with an add-in project. Sentry worked fine when we used version 2.1.6, but I wanted to upgrade to 3.6.1 yesterday and I couldn’t get any logging to come through. Confirmed that creating a standalone project using Sentry 3.6.1 worked correctly, will test a simple add-in project, as suggested, if I have time later today. We’re targeting .NET Framework 4.7.

The 3rd party application for which I’m developing an add-in project is Autodesk Revit, by the way. I don’t know what the software the others that are encountering this issue are developing for, maybe it’s the same, coincidentally?

Glad I am not the only one having issues with this. My 3rd party application is not Autodesk.

I have now created a new very simple add-in project with minimal other dependencies and it still fails with the same error.

Could you please share a link to a GitHub repo with this repro?

@bob

Can you try to clone this repo and see if it works for you? https://github.com/Tyrrrz-Contributions/sentry-netfx-repro (remember to change the DSN in Program.cs)

This is a clean WinForms project (dotnet new winforms) targeting net48. It’s able to send an event correctly and it shows up in Sentry.

@Tyrrrz
I can confirm that your sample works for me.
However, it still doesn’t work for me in the add-in application.

I think in regards to add-in application, the issue is that the add-in platform doesn’t respect binding redirects. A possible option, maybe, would be to use ILMerge to merge all assemblies into one, but honestly I don’t know if that would help.

@bob said that he could reproduce this issue on a non-add-in winforms project, so I was curious if my sample worked for him.

@Tyrrrz I cloned your project too and it works for me after adding in a System.Windows.Forms reference.

Interestingly, I downgraded the framework version to .NET 4.6.2 and nothing came through, even tried with Sentry 3.7.0 :man_shrugging: .

The Sentry SDK doesn’t have any special targets for .NET Framework. Only 4.6.1. .NET Framework has bugs related to dependency resolution Release sentry on nuget with net461 target · Issue #135 · getsentry/sentry-dotnet · GitHub when they tried to retrofit support for .NET Standard 2.0 on .NET Framework 4.6.1 and for that reason we’ve added a .NET Framework target to the SDK. It’s likely due to binding redirects and some dependency version conflict.

Regardless of what you target on your app (4.6.2 or 4.7.1 or higher) it picks the same Sentry SDK target/DLL/dependencies:

image

If you can provide us with a repro we can help you troubleshoot this, usually resolved through binding redirects or, as you already figured out, using a newer version of .NET Framework.

Or ideally/even better, move over to .NET Core.