dotnet/efcore · error · InvalidOperationException
The DbFunction '{function}' returns a SqlExpression of type
Error message
The DbFunction '{function}' returns a SqlExpression of type '{type}', which is a nullable value type. DbFunctions must return expressions with non-nullable value types, even when they may return 'null'. What it means
When a DbFunction registered with a custom HasTranslation is invoked, EF requires the returned SqlExpression to have a non-nullable value Type. This throw fires when translation returns a SqlExpression whose Type.IsNullableValueType() is true (e.g. int?, DateTime?, decimal?). EF's type-mapping/nullability system assumes DbFunction translations expose a non-nullable CLR type; the database-level nullability is expressed separately via the IsNullable flag.
Source
Thrown at src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs:66
/// <inheritdoc />
public virtual SqlExpression? Translate(
IModel model,
SqlExpression? instance,
MethodInfo method,
IReadOnlyList<SqlExpression> arguments,
IDiagnosticsLogger<DbLoggerCategory.Query> logger)
{
var dbFunction = model.FindDbFunction(method);
if (dbFunction != null)
{
if (dbFunction.Translation != null)
{
var translation = dbFunction.Translation.Invoke(
arguments.Select(e => _sqlExpressionFactory.ApplyDefaultTypeMapping(e)).ToList());
return translation.Type.IsNullableValueType()
? throw new InvalidOperationException(
RelationalStrings.DbFunctionNullableValueReturnType(
dbFunction.ModelName, dbFunction.ReturnType.ShortDisplayName()))
: translation;
}
var argumentsPropagateNullability = dbFunction.Parameters.Select(p => p.PropagatesNullability);
return dbFunction.IsBuiltIn
? _sqlExpressionFactory.Function(
dbFunction.Name,
arguments,
dbFunction.IsNullable,
argumentsPropagateNullability,
method.ReturnType.UnwrapNullableType(),
dbFunction.TypeMapping)
: _sqlExpressionFactory.Function(
dbFunction.Schema,
dbFunction.Name,View on GitHub (pinned to 3a2006ef56)
Solutions
- Return a SqlExpression whose Type is the non-nullable underlying type, e.g. typeof(int) instead of typeof(int?). Use the non-nullable CLR type when constructing SqlFunctionExpression / similar.
- If sourcing from a column expression, strip nullability: build a new expression with the non-nullable type mapping rather than reusing one typed as Nullable<T>.
- Express database nullability through the IsNullable parameter / type mapping, not through the CLR Type.
Example fix
// before
modelBuilder.HasDbFunction(mi)
.HasTranslation(args => new SqlFunctionExpression("FOO", args, true, new[] { true }, typeof(int?), null));
// after
modelBuilder.HasDbFunction(mi)
.HasTranslation(args => new SqlFunctionExpression("FOO", args, true, new[] { true }, typeof(int), null)); Defensive patterns
Strategy: validation
Validate before calling
// Ensure a HasTranslation returns a non-nullable value Type.
static SqlExpression NonNullResult(SqlExpression e, Type nonNullType)
=> e.Type == nonNullType
? e
: throw new InvalidOperationException($"DbFunction translation must return {nonNullType}, got {e.Type}.");
modelBuilder.HasDbFunction(method)
.HasTranslation(args => NonNullResult(
/* your SqlExpression */, typeof(int))); Prevention
- Always construct DbFunction translation results with non-nullable CLR types (int, not int?).
- Express database nullability via IsNullable/type mapping, not via Nullable<T>.
- Unit-test DbFunction translations against the type check before deploying.
When it happens
Trigger: modelBuilder.HasDbFunction(typeof(MyFunctions).GetMethod(nameof(MyFunctions.Foo))).HasTranslation(args => new SqlFunctionExpression("FOO", args, typeof(int?))); — any HasTranslation whose returned SqlExpression.Type is a Nullable<T>. Also when reusing an existing SqlExpression (e.g. a column) that carries int? as its Type.
Common situations: Custom DbFunction translations written to mirror a CLR signature that uses int?/DateTime?; copying a column expression (which often has a nullable Type) into the translation result; upgrading from a version that did not validate the return type.
Related errors
- The DbFunction '{function}' returns '{type}', but '{elementT
- The element type of the result of '{dbFunction}' is mapped t
- The parameter '{parameter}' for the DbFunction '{function}'
- The entity type '{entityType}' is mapped to the DbFunction n
- The entity type '{entityType}' is mapped to the 'DbFunction'
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/25463b907715f95b.
Report an issue: GitHub.