{"record":{"id":"512631e12a7cb1e4","repo":"dotnet/efcore","slug":"custom-translation-cannot-be-set-on-the-dbfunction","errorCode":null,"errorMessage":"Custom translation cannot be set on the DbFunction '{function}' since it is not a scalar function.","messagePattern":"Custom translation cannot be set on the DbFunction '(.+?)' since it is not a scalar function\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Metadata/Internal/DbFunction.cs","lineNumber":611,"sourceCode":"        set => SetTranslation(value, ConfigurationSource.Explicit);\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public virtual Func<IReadOnlyList<SqlExpression>, SqlExpression>? SetTranslation(\n        Func<IReadOnlyList<SqlExpression>, SqlExpression>? translation,\n        ConfigurationSource configurationSource)\n    {\n        EnsureMutable();\n\n        if (translation != null\n            && (!IsScalar || IsAggregate))\n        {\n            throw new InvalidOperationException(RelationalStrings.DbFunctionNonScalarCustomTranslation(MethodInfo?.DisplayName()));\n        }\n\n        _translation = translation;\n\n        _translationConfigurationSource = translation == null\n            ? null\n            : configurationSource.Max(_translationConfigurationSource);\n\n        return translation;\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public virtual ConfigurationSource? GetTranslationConfigurationSource()","sourceCodeStart":593,"sourceCodeEnd":629,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Metadata/Internal/DbFunction.cs#L593-L629","documentation":"Thrown by DbFunction.SetTranslation when a custom translation delegate is set on a function that is not a scalar, non-aggregate function (i.e. IsScalar is false or IsAggregate is true). Custom translation is only supported for scalar functions whose arguments map to a single SqlExpression result.","triggerScenarios":"Calling HasTranslation(...) on a table-valued function (IQueryable<T> return) or on a function marked IsAggregate. Surfaced through InternalDbFunctionBuilder.HasTranslation -> Metadata.SetTranslation.","commonSituations":"Applying a shared DbFunction configuration routine that calls HasTranslation to all functions, including TVFs and aggregates. Or trying to translate a TVF's row set the way you would a scalar.","solutions":["Remove the HasTranslation call from TVF and aggregate functions; custom translation applies only to scalar functions.","Guard: only set translation when the function is scalar and non-aggregate.","For TVFs, map them as queryable functions returning an entity type instead of providing a translation.","If the function is meant to be scalar, ensure its return type is a scalar so IsScalar is true and IsAggregate stays false."],"exampleFix":"// before\npublic IQueryable<Order> RecentOrders() => /* tvf */;\nmodelBuilder.HasDbFunction(typeof(Ctx).GetMethod(\"RecentOrders\"))\n    .HasTranslation(args => /* SqlExpression */ null!); // throws\n\n// after\npublic IQueryable<Order> RecentOrders() => /* tvf */;\nmodelBuilder.HasDbFunction(typeof(Ctx).GetMethod(\"RecentOrders\"));\n// HasTranslation only for scalar fns:\npublic decimal TaxFor(decimal amount) => 0m;\nmodelBuilder.HasDbFunction(typeof(Ctx).GetMethod(\"TaxFor\"))\n    .HasTranslation(args => new SqlBinaryExpression(...));","handlingStrategy":"validation","validationCode":"// Only set translation for scalar, non-aggregate functions\nif (fn.IsScalar && !fn.IsAggregate)\n{\n    fn.Builder.HasTranslation(translate, fromDataAnnotation: true);\n}","typeGuard":"static bool SupportsCustomTranslation(IDbFunction fn) => fn is { IsScalar: true, IsAggregate: false };","tryCatchPattern":null,"preventionTips":["Reserve HasTranslation for scalar functions only.","Separate TVF mapping (entity return) from scalar translation in config helpers.","Guard configuration loops with an IsScalar check before applying translation."],"tags":["efcore","dbfunction","tvf","translation","model-building"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}