dotnet/efcore · error · NotSupportedException

The literal expression

Error message

The literal expression '{expression}' for '{type}' cannot be parsed. Only simple constructor calls and factory methods are supported.

What it means

Thrown by CSharpHelper while scaffolding a design-time literal: the type mapping's GenerateCodeLiteral returned an expression tree whose shape the helper cannot render (it only understands simple constructor calls and static factory methods). This is a NotSupportedException raised during code generation for migrations/seeds or compiled-model literals.

Solutions

  1. Implement CoreTypeMapping.GenerateCodeLiteral on the custom type mapping to return a NewExpression or a static factory MethodCallExpression.
  2. If the literal is a default/discriminator/seed, replace the complex value with a primitive the scaffolder understands (string, int, GUID).
  3. Move the constant out of the model and apply it at runtime instead of via HasDefaultValue.
  4. Report the type to the provider author so GenerateCodeLiteral is supported upstream.

Example fix

// before - custom struct used as a default value produces an unmappable literal
modelBuilder.Entity<Foo>().Property(x => x.Custom).HasDefaultValue(CustomValue.Parse("abc"));

// after - generate a supported factory-method literal
public sealed class CustomValue
{
    public static Expression GenerateCodeLiteral(object v)
        => Expression.Call(typeof(CustomValue).GetMethod(nameof(Parse))!,
                           Expression.Constant(((CustomValue)v).Raw));
}
Defensive patterns

Strategy: validation

Validate before calling

var mapping = typeMappingSource.FindMapping(typeof(CustomValue));
if (mapping?.GenerateCodeLiteral(sample) is Expression e
    && !IsSimpleCtorOrFactory(e))
{
    throw new InvalidOperationException(
        "CustomValue literal cannot be scaffolded; implement GenerateCodeLiteral.");
}

Type guard

static bool IsSimpleCtorOrFactory(Expression e)
    => e is NewExpression or MethodCallExpression { Object: null };

Try / catch

try { helper.UnknownLiteral(value); }
catch (NotSupportedException ex) when (ex.Message.Contains("cannot be parsed"))
{ /* fall back to a primitive constant or compute at runtime */ }

Prevention

When it happens

Trigger: A value of a custom or third-party type is used as a model constant/default (HasDefaultValue, seed data, discriminator) and its CoreTypeMapping.GenerateCodeLiteral emits something other than NewExpression, factory MethodCallExpression, or a supported primitive expression. Nested complex expressions orMemberInit fall through HandleExpression and return false.

Common situations: Custom value converters whose target type has no code-literal support; NodaTime or other provider types used as column defaults; upgrading EF Core and a previously-supported literal shape is now rejected.

Related errors


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

Appendix: source

Thrown at src/EFCore.Design/Design/Internal/CSharpHelper.cs:1107

            var genericArguments = valueType.GetGenericArguments();
            switch (value)
            {
                case IList list when genericArguments.Length == 1 && valueType.GetGenericTypeDefinition() == typeof(List<>):
                    return List(genericArguments[0], list);
                case IDictionary dict when genericArguments.Length == 2 && valueType.GetGenericTypeDefinition() == typeof(Dictionary<,>):
                    return Dictionary(genericArguments[0], genericArguments[1], dict);
            }
        }

        var mapping = _typeMappingSource.FindMapping(literalType);
        if (mapping != null)
        {
            var builder = new StringBuilder();
            var expression = mapping.GenerateCodeLiteral(value);
            var handled = HandleExpression(expression, builder);

            return !handled
                ? throw new NotSupportedException(
                    DesignStrings.LiteralExpressionNotSupported(
                        expression.ToString(),
                        literalType.ShortDisplayName()))
                : builder.ToString();
        }

        throw new InvalidOperationException(DesignStrings.UnknownLiteral(literalType));
    }

    private bool HandleExpression(Expression expression, StringBuilder builder, bool simple = false)
    {
        // Only handle trivially simple cases for `new` and factory methods
        switch (expression.NodeType)
        {
            case ExpressionType.NewArrayInit:
                builder
                    .Append("new ")
                    .Append(Reference(expression.Type.GetElementType()!))

View on GitHub (pinned to 3a2006ef56)