{"record":{"id":"25463b907715f95b","repo":"dotnet/efcore","slug":"the-dbfunction-function-returns-a-sqlexpressio","errorCode":null,"errorMessage":"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'.","messagePattern":"The DbFunction '(.+?)' returns a SqlExpression of type '(.+?)', which is a nullable value type\\. DbFunctions must return expressions with non-nullable value types, even when they may return 'null'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs","lineNumber":66,"sourceCode":"\n    /// <inheritdoc />\n    public virtual SqlExpression? Translate(\n        IModel model,\n        SqlExpression? instance,\n        MethodInfo method,\n        IReadOnlyList<SqlExpression> arguments,\n        IDiagnosticsLogger<DbLoggerCategory.Query> logger)\n    {\n        var dbFunction = model.FindDbFunction(method);\n        if (dbFunction != null)\n        {\n            if (dbFunction.Translation != null)\n            {\n                var translation = dbFunction.Translation.Invoke(\n                    arguments.Select(e => _sqlExpressionFactory.ApplyDefaultTypeMapping(e)).ToList());\n\n                return translation.Type.IsNullableValueType()\n                    ? throw new InvalidOperationException(\n                        RelationalStrings.DbFunctionNullableValueReturnType(\n                            dbFunction.ModelName, dbFunction.ReturnType.ShortDisplayName()))\n                    : translation;\n            }\n\n            var argumentsPropagateNullability = dbFunction.Parameters.Select(p => p.PropagatesNullability);\n\n            return dbFunction.IsBuiltIn\n                ? _sqlExpressionFactory.Function(\n                    dbFunction.Name,\n                    arguments,\n                    dbFunction.IsNullable,\n                    argumentsPropagateNullability,\n                    method.ReturnType.UnwrapNullableType(),\n                    dbFunction.TypeMapping)\n                : _sqlExpressionFactory.Function(\n                    dbFunction.Schema,\n                    dbFunction.Name,","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Query/RelationalMethodCallTranslatorProvider.cs#L48-L84","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nmodelBuilder.HasDbFunction(mi)\n    .HasTranslation(args => new SqlFunctionExpression(\"FOO\", args, true, new[] { true }, typeof(int?), null));\n// after\nmodelBuilder.HasDbFunction(mi)\n    .HasTranslation(args => new SqlFunctionExpression(\"FOO\", args, true, new[] { true }, typeof(int), null));","handlingStrategy":"validation","validationCode":"// Ensure a HasTranslation returns a non-nullable value Type.\nstatic SqlExpression NonNullResult(SqlExpression e, Type nonNullType)\n    => e.Type == nonNullType\n        ? e\n        : throw new InvalidOperationException($\"DbFunction translation must return {nonNullType}, got {e.Type}.\");\n\nmodelBuilder.HasDbFunction(method)\n    .HasTranslation(args => NonNullResult(\n        /* your SqlExpression */, typeof(int)));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["efcore","dbfunction","translation","nullable","model-configuration"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}