dotnet/efcore · critical · InvalidOperationException

Model building is not supported when publishing with NativeA

Error message

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

What it means

Thrown by Column.Accessors getter when RuntimeFeature.IsDynamicCodeSupported is false — i.e. the app is published with NativeAOT, which forbids the reflection-based accessor generation EF normally does at runtime. Accessing the lazy-initialized ColumnAccessors under AOT would require dynamic code, so EF throws and directs you to a precompiled model.

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 dbf9771522)

Solutions

  1. Generate a compiled model: run `dotnet ef dbcontext optimize` (or `Optimize-DbContext` in PMC) and wire up the generated *ModelBuilder in OnModelCreating / UseModel.
  2. Remove or disable NativeAOT for this app if a compiled model is not feasible; set PublishAot=false.
  3. Regenerate the compiled model whenever the model changes (treat it as a build step, check in the generated files).
  4. Add a CI check that runs the app's first query under the AOT-published binary to catch regressions.

Example fix

// before
// csproj:
<PublishAot>true</PublishAot>
// DbContext uses normal model building -> throws at runtime

// after
// 1) dotnet ef dbcontext optimize --output-dir CompiledModel
// 2) register generated model
protected override void OnModelCreating(ModelBuilder modelBuilder)
    => new CompiledModel().CreateModel(modelBuilder);
// 3) UseDbContextModel is wired via options.UseModel(new CompiledModel())
Defensive patterns

Strategy: validation

Validate before calling

// Detect AOT/trimming at startup and refuse to run without a compiled model
if (!RuntimeFeature.IsDynamicCodeSupported && !typeof(MyDbContext).IsCompiledModelCached())
{
    throw new InvalidOperationException("Compiled model required under NativeAOT. Run 'dotnet ef dbcontext optimize'.");
}

Try / catch

// Wrap the first DB operation in startup checks
try { _ = ctx.Users.First(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("NativeAOT"))
{
    logger.LogCritical("Compiled model missing; run 'dotnet ef dbcontext optimize'");
    throw;
}

Prevention

When it happens

Trigger: Publishing an EF Core relational app with PublishAot=true (or PublishReadyToRun with trimming/AOT) without first generating a compiled model. The exception fires the first time the runtime accesses per-column value accessors (typically during query materialization or SaveChanges).

Common situations: New .NET 8+ projects enabling NativeAOT for startup/size and forgetting EF needs a compiled model. CI producing AOT images that pass build but fail at first DB call. Upgrading an app to AOT publishing without regenerating the model.

Related errors


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