{"record":{"id":"f6a3c30ff480e541","repo":"JamesNK/Newtonsoft.Json","slug":"property-does-not-have-a-setter","errorCode":null,"errorMessage":"Property does not have a setter.","messagePattern":"Property does not have a setter\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs","lineNumber":348,"sourceCode":"            // use reflection for structs\n            // expression doesn't correctly set value\n            if (propertyInfo.DeclaringType!.IsValueType())\n            {\n                return LateBoundReflectionDelegateFactory.Instance.CreateSet<T>(propertyInfo);\n            }\n\n            Type instanceType = typeof(T);\n            Type valueType = typeof(object);\n\n            ParameterExpression instanceParameter = Expression.Parameter(instanceType, \"instance\");\n\n            ParameterExpression valueParameter = Expression.Parameter(valueType, \"value\");\n            Expression readValueParameter = EnsureCastExpression(valueParameter, propertyInfo.PropertyType);\n\n            MethodInfo? setMethod = propertyInfo.GetSetMethod(true);\n            if (setMethod == null)\n            {\n                throw new ArgumentException(\"Property does not have a setter.\");\n            }\n\n            Expression setExpression;\n            if (setMethod.IsStatic)\n            {\n                setExpression = Expression.Call(setMethod, readValueParameter);\n            }\n            else\n            {\n                Expression readInstanceParameter = EnsureCastExpression(instanceParameter, propertyInfo.DeclaringType!);\n\n                setExpression = Expression.Call(readInstanceParameter, setMethod, readValueParameter);\n            }\n\n            LambdaExpression lambdaExpression = Expression.Lambda(typeof(Action<T, object?>), setExpression, instanceParameter, valueParameter);\n\n            Action<T, object?> compiled = (Action<T, object?>)lambdaExpression.Compile();\n            return compiled;","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Utilities/ExpressionReflectionDelegateFactory.cs#L330-L366","documentation":"Thrown by ExpressionReflectionDelegateFactory.CreateSet(PropertyInfo) when propertyInfo.GetSetMethod(true) returns null, i.e. the property has no set accessor at all (public or private). The Expression factory is used for reference types; structs are routed to the LateBound factory instead, so this path only fires on classes. It surfaces during deserialization when Json.NET attempts to build a setter delegate to populate a read-only property.","triggerScenarios":"Deserializing JSON into a reference type whose property is declared get-only (e.g. `public string Name { get; }`), where the contract resolver selects that property for population. Also any direct call to CreateSet<T>(PropertyInfo) on a PropertyInfo returned by GetSetMethod(true) == null.","commonSituations":"Immutable DTOs or records using get-only auto-properties, computed read-only properties, properties whose backing field is only set in a constructor, or a refactor that removed a setter. Also migrating to C# 6+ get-only auto-properties without updating serialization.","solutions":["Add a private setter to the property (`public string Name { get; private set; }`) — GetSetMethod(true) finds non-public setters and the error disappears.","Annotate the read-only property with [JsonIgnore] so the serializer skips it entirely.","Use a custom IContractResolver (e.g. derive from DefaultContractResolver) that filters out read-only properties in CreateProperties.","Use [OnDeserialized] / constructor deserialization with [JsonConstructor] to populate the field instead of the property."],"exampleFix":"// before\npublic string Name { get; }\n\n// after\npublic string Name { get; private set; }","handlingStrategy":"validation","validationCode":"// Before handing a PropertyInfo to a setter pipeline, ensure it is settable.\nbool CanSet(PropertyInfo p) => p.GetSetMethod(true) != null;","typeGuard":"static bool IsSettable(PropertyInfo p) => p.GetSetMethod(true) != null;","tryCatchPattern":null,"preventionTips":["Default to private setters on DTO properties so serialization can populate them.","Use a custom IContractResolver that omits read-only properties from the contract.","Run a unit test that round-trips each DTO to catch read-only property issues early."],"tags":["reflection","deserialization","property","readonly","setter"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}