dotnet/efcore · error · InvalidOperationException

Model building is not supported when publishing with…

Error message

Model building is not supported when publishing with NativeAOT. Use a compiled model.

What it means

Under NativeAOT (RuntimeFeature.IsDynamicCodeSupported is false), EF Core cannot use reflection to build the per-column accessor delegates at runtime. The Column.Accessors getter throws to tell you to use a pre-built compiled model instead of runtime model building. This is enforced at every place EF would otherwise emit reflection-based code.

Solutions

  1. Generate a compiled model: run 'dotnet ef dbcontext optimize' (or Microsoft.EntityFrameworkCore.Design's optimized-model scaffold) and wire the generated DbContextModel into your options via UseModel(MyCompiledModel.Model).
  2. Confirm <PublishAot>true</PublishAot> is intended; if AOT is not required, disable it to allow runtime model building.
  3. Re-run the compiled-model generation whenever the model changes so it stays in sync with the DbContext.

Example fix

// before
var options = new DbContextOptionsBuilder<AppDb>()
    .UseSqlServer(connectionString)
    .Options;

// after (enable compiled model under AOT)
var options = new DbContextOptionsBuilder<AppDb>()
    .UseSqlServer(connectionString)
    .UseModel(AppDbCompiledModel.Model)
    .Options;
Defensive patterns

Strategy: validation

Validate before calling

// Detect AOT early and fail fast with guidance
if (!RuntimeFeature.IsDynamicCodeSupported
    && !(optionsBuilder.Options.FindExtension<CoreOptionsExtension>()?.PrecompiledModel ?? false))
{
    throw new InvalidOperationException("NativeAOT detected: call UseModel(...) with a compiled model.");
}

Type guard

static bool RequiresCompiledModel()
    => !System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported;

Prevention

When it happens

Trigger: Publishing an app with <PublishAot>true</PublishAot> while constructing the DbContext with new DbContext(options) (runtime model building) instead of a generated CompiledModel. The exception surfaces the first time EF needs column accessors.

Common situations: Enabling NativeAOT late in a project's lifecycle without regenerating the compiled model; CI pipeline shipping AOT builds for the first time; upgrading EF Core and assuming the previous runtime model still works under AOT.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Metadata/Internal/Column.cs:58

    ///     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 new virtual Table Table
        => (Table)base.Table;

    /// <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 ColumnAccessors Accessors
    {
        get => NonCapturingLazyInitializer.EnsureInitialized(
            ref _accessors, this, static column =>
                RuntimeFeature.IsDynamicCodeSupported
                    ? ColumnAccessorsFactory.Create(column)
                    : throw new InvalidOperationException(CoreStrings.NativeAotNoCompiledModel));
        set => _accessors = value;
    }

    /// <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 override string ToString()
        => ((IColumn)this).ToDebugString(MetadataDebugStringOptions.SingleLineDefault);

    /// <inheritdoc />
    ITable IColumn.Table
    {
        [DebuggerStepThrough]
        get => Table;
    }

View on GitHub (pinned to 3a2006ef56)