{"record":{"id":"5409cba02b5d80d3","repo":"dotnet/efcore","slug":"executeupdatecannotsetjsonpropertytoarbitraryexpre","errorCode":"ExecuteUpdateCannotSetJsonPropertyToArbitraryExpression","errorMessage":"'ExecuteUpdate' cannot currently set a property in a JSON column to arbitrary expressions; only constants, parameters and other JSON properties are supported; see https://github.com/dotnet/efcore/issues/36688.","messagePattern":"'ExecuteUpdate' cannot currently set a property in a JSON column to arbitrary expressions; only constants, parameters and other JSON properties are supported; see https://github\\.com/dotnet/efcore/issues/36688\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs","lineNumber":391,"sourceCode":"                    var typeMapping = jsonScalar.TypeMapping;\n                    Check.DebugAssert(typeMapping is not null);\n\n                    // We should never see a JsonScalarExpression without a path - that means we're mapping a JSON scalar directly to a relational column.\n                    // This is in theory possible (e.g. map a DateTime to a 'json' column with a single string timestamp representation inside, instead of to\n                    // SQL Server datetime2), but contrived and unsupported.\n                    Check.DebugAssert(jsonScalar.Path.Count > 0);\n\n                    ProcessColumn(jsonColumn, targetProperty);\n\n                    var translatedValue = TranslateScalarSetterValueSelector(source, valueSelector, jsonScalar.Type, typeMapping);\n\n                    // We now have the relational scalar expression for the value; but we need the JSON representation to pass to the provider's JSON modification\n                    // function (e.g. SQL Server JSON_MODIFY()).\n                    // For example, for a DateTime we'd have e.g. a SqlConstantExpression containing a DateTime instance, but we need a string containing\n                    // the JSON-encoded ISO8601 representation.\n                    if (!TrySerializeScalarToJson(jsonScalar, translatedValue, out var jsonValue))\n                    {\n                        throw new InvalidOperationException(\n                            translatedValue is ColumnExpression\n                                ? RelationalStrings.ExecuteUpdateCannotSetJsonPropertyToNonJsonColumn\n                                : RelationalStrings.ExecuteUpdateCannotSetJsonPropertyToArbitraryExpression);\n                    }\n\n                    // We now have a serialized JSON value (number, string or bool) - generate a setter for it.\n                    GenerateJsonPartialUpdateSetterWrapper(jsonScalar, jsonColumn, jsonValue);\n                    continue;\n                }\n\n                case StructuralTypeShaperExpression { ValueBufferExpression: JsonQueryExpression jsonQuery }:\n                    ProcessStructuralJsonSetter(jsonQuery);\n                    continue;\n\n                case CollectionResultExpression { QueryExpression: JsonQueryExpression jsonQuery }:\n                    ProcessStructuralJsonSetter(jsonQuery);\n                    continue;\n","sourceCodeStart":373,"sourceCodeEnd":409,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs#L373-L409","documentation":"Same JSON-scalar setter path (line 371-400), but here the value is neither a ColumnExpression nor one of the supported shapes (constant, parameter, or another JsonScalarExpression). TrySerializeScalarToJson returns false for arbitrary expressions, so the else branch at line 391-394 throws ExecuteUpdateCannotSetJsonPropertyToArbitraryExpression (issue #36688). Only constants, parameters, and JSON-to-JSON property copies are supported.","triggerScenarios":"Assigning a computed/arbitrary expression to a JSON scalar: SetProperty(e => e.Json.Counter, e => e.Json.Counter + 1), SetProperty(e => e.Json.Score, e => SomeMethod()), or any function-call/arithmetic expression targeting a JSON path.","commonSituations":"Trying to increment a JSON counter server-side; calling EF.Functions or custom methods in the value lambda for a JSON property; combining columns/JSON values arithmetically into a JSON target.","solutions":["Read the current value client-side, compute the new value, and pass it as a constant/parameter.","Use raw SQL with the database's JSON modification function (e.g. JSON_MODIFY) for server-side computation.","Restrict JSON-scalar SetProperty values to literals, captured variables (parameters), or another JSON scalar property copy."],"exampleFix":"// before (arithmetic on a JSON path is not supported)\ndb.Blogs.ExecuteUpdate(s => s.SetProperty(\n    b => b.Json.ViewCount, b => b.Json.ViewCount + 1));\n\n// after (compute client-side, pass as a parameter)\nvar current = await db.Blogs.Where(b => b.Id == id)\n    .Select(b => b.Json.ViewCount).FirstAsync();\ndb.Blogs.Where(b => b.Id == id)\n    .ExecuteUpdate(s => s.SetProperty(\n        b => b.Json.ViewCount, current + 1));","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { await q.ExecuteUpdateAsync(s => s.SetProperty(e => e.Json.Counter, e => e.Json.Counter + 1)); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"arbitrary expressions\"))\n{ /* compute client-side and pass as parameter; or use raw SQL JSON functions */ }","preventionTips":["Restrict JSON scalar SetProperty values to constants, parameters, or JSON-to-JSON property copies.","Compute increments/transformations client-side before ExecuteUpdate.","Reserve server-side JSON math for raw SQL where the DB supports it."],"tags":["efcore","executeupdate","json","setproperty"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}