microsoft / microsoft/agent-framework
.NET: [Bug]: JsonWireSerializedValue violates the equality and hash code contract
@peibekwe is already working on this.
Since Aug 31, 2026.
- 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.