dotnet/efcore · error · InvalidOperationException

'ExecuteUpdate' cannot currently set a property in a JSON co

Error message

'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.

What it means

Sibling of 606, same JsonScalarExpression case of TrySerializeScalarToJson failing, but here the translatedValue is NOT a ColumnExpression — it is some arbitrary SQL expression the JSON serializer cannot handle. JSON modification functions only accept constants, parameters, or other JSON properties.

Source

Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs:391

                    var typeMapping = jsonScalar.TypeMapping;
                    Check.DebugAssert(typeMapping is not null);

                    // We should never see a JsonScalarExpression without a path - that means we're mapping a JSON scalar directly to a relational column.
                    // This is in theory possible (e.g. map a DateTime to a 'json' column with a single string timestamp representation inside, instead of to
                    // SQL Server datetime2), but contrived and unsupported.
                    Check.DebugAssert(jsonScalar.Path.Count > 0);

                    ProcessColumn(jsonColumn, targetProperty);

                    var translatedValue = TranslateScalarSetterValueSelector(source, valueSelector, jsonScalar.Type, typeMapping);

                    // We now have the relational scalar expression for the value; but we need the JSON representation to pass to the provider's JSON modification
                    // function (e.g. SQL Server JSON_MODIFY()).
                    // For example, for a DateTime we'd have e.g. a SqlConstantExpression containing a DateTime instance, but we need a string containing
                    // the JSON-encoded ISO8601 representation.
                    if (!TrySerializeScalarToJson(jsonScalar, translatedValue, out var jsonValue))
                    {
                        throw new InvalidOperationException(
                            translatedValue is ColumnExpression
                                ? RelationalStrings.ExecuteUpdateCannotSetJsonPropertyToNonJsonColumn
                                : RelationalStrings.ExecuteUpdateCannotSetJsonPropertyToArbitraryExpression);
                    }

                    // We now have a serialized JSON value (number, string or bool) - generate a setter for it.
                    GenerateJsonPartialUpdateSetterWrapper(jsonScalar, jsonColumn, jsonValue);
                    continue;
                }

                case StructuralTypeShaperExpression { ValueBufferExpression: JsonQueryExpression jsonQuery }:
                    ProcessStructuralJsonSetter(jsonQuery);
                    continue;

                case CollectionResultExpression { QueryExpression: JsonQueryExpression jsonQuery }:
                    ProcessStructuralJsonSetter(jsonQuery);
                    continue;

View on GitHub (pinned to 3a2006ef56)

Solutions

  1. Compute the value in application code and pass it as a parameter/constant.
  2. Restrict JSON-setter value selectors to constants, captured variables (parameters), or another JSON property reference.
  3. Track #36688 for broader expression support.

Example fix

// before
.ExecuteUpdate(s => s.SetProperty(e => e.Config.Score, e => e.A + e.B));
// after
var score = a + b;
.ExecuteUpdate(s => s.SetProperty(e => e.Config.Score, score));
Defensive patterns

Strategy: validation

Validate before calling

// Ensure the JSON value selector is a constant, parameter, or JSON property reference.
var value = ComputeScore();
await ctx.Set<Root>().ExecuteUpdateAsync(s => s.SetProperty(e => e.Config.Score, value));

Prevention

When it happens

Trigger: SetProperty into a JSON scalar path whose value selector translates to a function call, arithmetic, or any non-constant/non-parameter expression (e.g. SetProperty(e => e.Config.Score, e => e.A + e.B)).

Common situations: Computing the new JSON value inline; using database functions inside the value selector of a JSON setter.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/a123c818eabed45e. Report an issue: GitHub.