microsoft / microsoft/agent-framework

.NET: [Bug]: JsonWireSerializedValue violates the equality and hash code contract

Open
#7,958 1 comment 0 reactions 1 assignee View on GitHub

@peibekwe is already working on this.

Since Aug 31, 2026.

.NET reproduced workflows
Dominant language
Python
Stars
13.6k
Forks
2.3k
Avg merge
2d 45m
Merged PRs (30d)
358

Description

### Description

JsonWireSerializedValue.Equals() compares two wrapped JSON values using JsonElement.DeepEquals(). However, GetHashCode() returns JsonElement.GetHashCode().

JsonElement.GetHashCode() is not a structural hash. Consequently, two JsonWireSerializedValue instances containing structurally identical JSON can compare equal while returning different hash codes.

This violates the .NET equality contract that equal objects must return the same hash code. It can cause unexpected behavior when delayed checkpoint values, including values wrapped by PortableValue, are used in hash-based collections such as Dictionary or HashSet.

Steps to reproduce

1. Parse the same JSON into two separate JsonDocument instances.
2. Wrap each root element in a separate JsonWireSerializedValue.
3. Compare the wrappers using Equals().
4. Compare their hash codes.

Actual behavior
The instances compare equal because Equals() uses structural JSON comparison, but their hash codes can differ because GetHashCode() delegates to JsonElement.GetHashCode().

Using .NET SDK 10.0.303, the underlying behavior was:
```
DeepEquals=True
HashA=182591433 HashB=1799979978 EqualHashes=False
```

Expected behavior
If two JsonWireSerializedValue instances compare equal, their hash codes should also be equal.

GetHashCode() should use a structural hash implementation whose semantics are consistent with JsonElement.DeepEquals().

### Code Sample

```markdown
[Fact]
public void GetHashCode_StructurallyEqualJson_ReturnsSameHashCode()
{
// Arrange
var serializer = new JsonMarshaller();

using JsonDocument firstDocument =
JsonDocument.Parse("""{"a":1,"b":[true,null]}""");
using JsonDocument secondDocument =
JsonDocument.Parse("""{"a":1,"b":[true,null]}""");

var first = new JsonWireSerializedValue(
serializer,
firstDocument.RootElement);

var second = new JsonWireSerializedValue(
serializer,
secondDocument.RootElement);

// Act
bool areEqual = first.Equals(second);
int firstHashCode = first.GetHashCode();
int secondHashCode = second.GetHashCode();

// Assert
Assert.True(areEqual);
Assert.Equal(firstHashCode, secondHashCode);
}
```

### Error Messages / Stack Traces

```markdown
No exception is thrown. The issue manifests as inconsistent behavior in hash-based collections.
```

### Package Versions

Microsoft.Agents.AI.Workflows: current main branch, commit 1aca2a95e

### .NET Version

.NET SDK 10.0.303

### Additional Context

_No response_

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.