Case Study
← All case studiesAssignment in Getter in Newtonsoft.Json
Context
Newtonsoft.Json PR#1950 modified XmlNodeConverter.cs. It introduced a property getter that also performs a write - assigning a value inside what should be a pure read operation. Property getters are expected to be side-effect-free. When a getter mutates state, callers using reflection, lazy initialization, caching layers, or serialization frameworks may observe inconsistent behavior because they assume reads are safe to repeat without side effects.
Diff evidence
[GCI0036] Pure Context Mutation
Location : src/Newtonsoft.Json/Converters/XmlNodeConverter.cs
Summary : Assignment in getter - mutation in a pure context.
Evidence : _nodeType = GetCurrentNodeType();
Why : Property getters are expected to be side-effect free. Mutations break
this contract and can cause subtle bugs with lazy initialization,
caching, or framework reflection.
Action : Move state mutations to setter, constructor, or a dedicated method.Why it matters
Newtonsoft.Json is the most downloaded NuGet package ever, with well over 3 billion downloads. Any serialization framework, ORM, or reflection-based tool that reads this property twice may see different values if the underlying state changes between reads. JSON.NET itself reads node properties repeatedly during traversal. A getter that writes state creates a timing dependency between reads - a class of bug that is nearly impossible to reproduce in unit tests (which call the getter once in a controlled sequence) but surfaces intermittently in production under concurrent serialization workloads.
Detection rules
- GCI0036 - Pure Context Mutation - flags assignments inside property getters.
- GCI0004 - Breaking Change Risk - flags public API changes that break callers.
