Add /analyze-crash and /analyze-error Claude commands by bouwkast · Pull Request #7961 · DataDog/dd-trace-dotnet

@bouwkast @andrewlock

## Summary of changes

This resolves a `System.InvalidCastException` that was happening in the
GRPC client instrumentation (I think just GrpcLegacy) when we attempted
to remove headers.


## Reason for change

Errors in Error Tracking

## Implementation details

> before

```
public void Remove(string name)
{
    var entry = _headers.Get(name);
    if (entry is not null)
    {
        _headers.Remove(name);
    }
}
```

> after
```
public void Remove(string name)
{
    var entry = _headers.Get(name);
    if (entry is not null)
    {
        _headers.Remove(entry);
    }
}
```

## Test coverage

Updated the sample application to detect this and if it is detected it
adds a tag which causes the tests to fail (and they did fail before I
applied the fix).

## Other details
<!-- Fixes #{issue} -->

Used #7961
`/analyze-error` command based on the reported error in Error Tracking.
Seemed to work okay, it identified the issue, follow up was able to get
a reproduction quickly, but it really struggled to get the tests
updated.

Helpfully, the command output a document that linked to and copied the
actual `Grpc.Core.Api` code that we hit 👍
Saves some time searching on GitHub ourselves I guess.

This is a bit of an edge case here so I don't think very wide spread.

Reproduced Error:

```
2025-12-18 10:03:42.678 -05:00 [ERR] Error creating inactive client span for GRPC call System.InvalidCastException: Unable to cast object of type 'System.String' to type 'Entry'.
   at Grpc_Core_Api__D754F35622E28BAD.Grpc_Core_Metadata.Datadog_Trace_ClrProfiler_AutoInstrumentation_Grpc_IMetadata_3.Remove(Object )
   at Datadog.Trace.ClrProfiler.AutoInstrumentation.Grpc.MetadataHeadersCollection.Remove(String name)
   at Datadog.Trace.ClrProfiler.AutoInstrumentation.Grpc.MetadataHeadersCollection.Set(String name, String value)
   at Datadog.Trace.Headers.HeadersCollectionAccesor`1.Set(TCarrier carrier, String key, String value)
   at Datadog.Trace.Propagators.W3CTraceContextPropagator.Inject[TCarrier,TCarrierSetter](PropagationContext context, TCarrier carrier, TCarrierSetter carrierSetter)
   at Datadog.Trace.Propagators.SpanContextPropagator.Inject[TCarrier,TCarrierSetter](PropagationContext context, TCarrier carrier, TCarrierSetter carrierSetter)
   at Datadog.Trace.Propagators.SpanContextPropagator.Inject[TCarrier](PropagationContext context, TCarrier headers)
   at Datadog.Trace.ClrProfiler.AutoInstrumentation.Grpc.GrpcLegacy.Client.GrpcLegacyClientCommon.InjectHeaders[TMethod,TCallOptions](Tracer tracer, TMethod method, TCallOptions& callOptionsInstance)
 { MachineName: ".", Process: "[84684 Samples.GrpcLegacy]", AppDomain: "[1 Samples.GrpcLegacy.exe]", TracerVersion: "3.34.0.0" }

```
<!--  ⚠️ Note:

Where possible, please obtain 2 approvals prior to merging. Unless
CODEOWNERS specifies otherwise, for external teams it is typically best
to have one review from a team member, and one review from apm-dotnet.
Trivial changes do not require 2 reviews.

MergeQueue is NOT enabled in this repository. If you have write access
to the repo, the PR has 1-2 approvals (see above), and all of the
required checks have passed, you can use the Squash and Merge button to
merge the PR. If you don't have write access, or you need help, reach
out in the #apm-dotnet channel in Slack.
-->

---------

Co-authored-by: Andrew Lock <andrew.lock@datadoghq.com>