dotnet/efcore · error · InvalidOperationException

Cannot scaffold C# literals of type

Error message

Cannot scaffold C# literals of type '{literalType}'. The provider should implement CoreTypeMapping.GenerateCodeLiteral to support using it at design time.

What it means

Thrown by CSharpHelper.UnknownLiteral when no CoreTypeMapping can be found for the literal type at all — FindMapping returns null, so there is nothing capable of producing code for the value. InvalidOperationException, surfaced while generating literals for migrations, seeds, or the compiled model.

Solutions

  1. Register a value converter for the property so it maps to a primitive the provider understands.
  2. Avoid using the un-mapped type as HasDefaultValue/seed data; compute it at runtime instead.
  3. Update the provider package to a version that ships a mapping for the type.
  4. Implement and register an ITypeMappingSource plugin that returns a mapping for the literal type.

Example fix

// before
modelBuilder.Entity<T>().Property(x => x.Custom).HasDefaultValue(new CustomStruct());

// after - convert to a mapped primitive and apply default at runtime
modelBuilder.Entity<T>()
    .Property(x => x.Custom)
    .HasConversion(v => v.Serialize(), s => CustomStruct.Deserialize(s));
Defensive patterns

Strategy: validation

Validate before calling

var mapping = typeMappingSource.FindMapping(literalType);
if (mapping is null)
{
    throw new InvalidOperationException(
        $"No type mapping for {literalType}; register a value converter or pick a mapped type.");
}

Type guard

static bool TypeIsMapped(ITypeMappingSource src, Type t)
    => src.FindMapping(t) is not null;

Try / catch

try { helper.UnknownLiteral(value); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Cannot scaffold"))
{ /* register a converter or remove the literal */ }

Prevention

When it happens

Trigger: Using a value type as a constant/default/seed for which neither EF Core nor the active provider registers a type mapping. Common with clr types the provider does not natively map (e.g. Half, DateOnly on older providers, custom structs without a converter).

Common situations: Upgrading the database provider to a version that no longer maps a type, switching providers (SQL Server -> PostgreSQL) where a previously-mapped type is unsupported, or introducing a custom value object as a column default without a converter.

Related errors


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

Appendix: source

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

            }
        }

        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()!))
                    .Append("[] { ");

                HandleList(((NewArrayExpression)expression).Expressions, builder, simple: true);

                builder
                    .Append(" }");

View on GitHub (pinned to 3a2006ef56)