dotnet/efcore · error · InvalidOperationException

'IsNullable' cannot be set on DbFunction '{functionName}' si

Error message

'IsNullable' cannot be set on DbFunction '{functionName}' since the function does not represent a scalar function.

What it means

Thrown by DbFunction.SetIsNullable when IsScalar is false (the function returns IQueryable<T>, i.e. it is a table-valued function). Nullability of a return value only makes sense for scalar functions; a TVF returns a row set, so 'nullable' is meaningless and EF rejects the configuration.

Source

Thrown at src/EFCore.Relational/Metadata/Internal/DbFunction.cs:476

    public virtual bool IsNullable
    {
        get => _nullable;
        set => SetIsNullable(value, ConfigurationSource.Explicit);
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual bool SetIsNullable(bool nullable, ConfigurationSource configurationSource)
    {
        EnsureMutable();

        if (!IsScalar)
        {
            throw new InvalidOperationException(RelationalStrings.NonScalarFunctionCannotBeNullable(Name));
        }

        _nullable = nullable;
        _nullableConfigurationSource = configurationSource.Max(_nullableConfigurationSource);

        return nullable;
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public virtual ConfigurationSource? GetIsNullableConfigurationSource()
        => _nullableConfigurationSource;

    /// <summary>

View on GitHub (pinned to dbf9771522)

Solutions

  1. Remove the IsNullable call for table-valued functions; only set it for scalar DbFunctions.
  2. Guard the call: only apply IsNullable when the function is scalar.
  3. Split configuration into scalar vs TVF branches so TVFs skip nullability.
  4. If you intended a scalar function, change the return type to a scalar type first.

Example fix

// before
public IQueryable<Order> RecentOrders() => /* tvf */;
modelBuilder.HasDbFunction(typeof(Ctx).GetMethod("RecentOrders"))
    .HasAnnotation(RelationalAnnotationNames.DbFunctionIsNullable, true); // throws

// after
public IQueryable<Order> RecentOrders() => /* tvf */;
modelBuilder.HasDbFunction(typeof(Ctx).GetMethod("RecentOrders"));
// (do not set IsNullable on a TVF)
Defensive patterns

Strategy: validation

Validate before calling

// Only apply IsNullable to scalar functions
foreach (var fn in modelBuilder.Model.GetDbFunctions().Where(f => f.IsScalar))
{
    fn.Builder.IsNullable(true, fromDataAnnotation: true);
}

Type guard

static bool CanSetNullable(IDbFunction fn) => fn.IsScalar;

Prevention

When it happens

Trigger: Calling builder.IsNullable(...) (HasAnnotation/IsNullable fluent) on a DbFunction that returns IQueryable<T>. Surfaced through InternalDbFunctionBuilder.IsNullable -> Metadata.SetIsNullable.

Common situations: Developers apply a generic DbFunction configuration helper that sets IsNullable to every registered function, including TVFs. Or copy scalar-function config onto a TVF.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/4d30e0fa0957e309. Report an issue: GitHub.