dotnet/efcore · error · InvalidOperationException

The DbFunction ' ' has an invalid return type ' '. Ensure…

Error message

The DbFunction '{function}' has an invalid return type '{type}'. Ensure that the return type can be mapped by the current provider.

What it means

ValidateDbFunction throws DbFunctionInvalidReturnType when a scalar DbFunction has no resolved type mapping (dbFunction.TypeMapping == null). The provider could not map the function's return type to a store type, meaning the CLR return type is unsupported by the current provider. Distinct from the IQueryable-return variant (359) which targets owned-entity returns.

Solutions

  1. Change the DbFunction's return type to one the provider maps natively (int, string, DateTime, double, etc.).
  2. Register a value converter / type mapping for the custom return type before defining the DbFunction.
  3. If wrapping a database function returning an exotic type, expose it through a SQL view or compute a primitive in the method body.

Example fix

// before — MoneyAmount is a custom struct with no mapping
public static MoneyAmount Total(this DbContext db, int id)
    => throw new NotImplementedException();
modelBuilder.HasDbFunction(typeof(MyCtx).GetMethod(nameof(MyCtx.Total))!); // throws

// after — return decimal, convert at the call site
public static decimal Total(this DbContext db, int id)
    => throw new NotImplementedException();
Defensive patterns

Strategy: validation

Validate before calling

if (dbFunction.IsScalar && dbFunction.TypeMapping is null)
    throw new InvalidOperationException($"DbFunction {dbFunction.ModelName} return type {dbFunction.ReturnType} has no mapping.");

Type guard

static bool HasScalarMapping(IDbFunction f)
    => !f.IsScalar || f.TypeMapping is not null;

Prevention

When it happens

Trigger: Registering HasDbFunction for a method whose return CLR type has no relational type mapping — e.g. a custom struct, an unsupported primitive, or a type whose mapping requires a value converter not configured for DbFunction resolution. Only fires when dbFunction.IsScalar and TypeMapping is null.

Common situations: Using a provider-specific function returning a type the provider doesn't map by default (e.g. timespan, char, decimal with unusual scale); registering a DbFunction whose return type is a domain enum without configuring the enum conversion; upgrading the provider and losing a previously-inferred mapping.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:367

        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
    }

    /// <summary>
    ///     Validates a single database function.
    /// </summary>
    /// <param name="dbFunction">The database function to validate.</param>
    /// <param name="logger">The logger to use.</param>
    protected virtual void ValidateDbFunction(
        IDbFunction dbFunction,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        var model = dbFunction.Model;
        if (dbFunction.IsScalar)
        {
            if (dbFunction.TypeMapping == null)
            {
                throw new InvalidOperationException(
                    RelationalStrings.DbFunctionInvalidReturnType(
                        dbFunction.ModelName,
                        dbFunction.ReturnType.ShortDisplayName()));
            }
        }
        else
        {
            var elementType = dbFunction.ReturnType.GetGenericArguments()[0];
            var entityType = model.FindEntityType(elementType);

            if (entityType?.IsOwned() == true
                || ((IConventionModel)model).IsOwned(elementType)
                || (entityType == null && model.GetEntityTypes().Any(e => e.ClrType == elementType)))
            {
                throw new InvalidOperationException(
                    RelationalStrings.DbFunctionInvalidIQueryableOwnedReturnType(
                        dbFunction.ModelName, elementType.ShortDisplayName()));
            }

View on GitHub (pinned to 3a2006ef56)