Skip to content

Adding .ConfigureAwait() to async query causes precompiled query generation to fail #37961

Closed

Description

@donpanl

Bug description

An async query can have .ConfigureAwait() appended:

return await context.Blogs.FirstAsync(localCt).ConfigureAwait(false);

In that case, query precompilation fails with error:

System.InvalidOperationException: Query precompilation failed with errors:
QueryPrecompilationError { SyntaxNode = context.Blogs.FirstAsync(localCt), Exception = System.InvalidOperationException: Encountered unknown identifier name 'localCt', which doesn't correspond to a lambda parameter or captured variable
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }

   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.PrecompileQueries(String outputDir, DbContext context, String suffix, IServiceProvider services, IReadOnlyDictionary`2 memberAccessReplacements, ISet`1 generatedFileNames)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String suffix, Boolean scaffoldModel, Boolean precompileQueries, DbContext context, Boolean optimizeAllInAssembly, Boolean nativeAot, List`1 generatedFiles, HashSet`1 generatedFileNames)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String contextTypeName, String suffix, Boolean scaffoldModel, Boolean precompileQueries, Boolean nativeAot)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeContextImpl(String outputDir, String modelNamespace, String contextType, String suffix, Boolean scaffoldModel, Boolean precompileQueries, Boolean nativeAot)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)

Precompilation succeeds if parameterless .FirstAsync() is used or if .ConfigureAwait() call is separated from the query:

var task = context.Blogs.FirstAsync(localCt);
return await task.ConfigureAwait(false);

See attached project with minimal example.

Can be reproduced with:

> dotnet publish --ucr --sc

confawait.zip

Your code

--- Model.cs

public class Blog
{
    public int Id { get; set; }
}

--- Context.cs

using Microsoft.EntityFrameworkCore;

public class Context : DbContext
{
    public DbSet<Blog> Blogs { get; set; } = null!;

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlite("Data Source=tmp.db");
    }
}

--- Program.cs

using Microsoft.EntityFrameworkCore;

public static class Program
{
    public static async Task<int> Main(string[] args)
    {
        var cts = new CancellationTokenSource();
        _ = await QueryAsync(cts.Token);
        return 0;
    }

    private static async Task<Blog> QueryAsync(CancellationToken ct)
    {
        await using var context = new Context();
        var localCt = ct;
        // var task = context.Blogs.FirstAsync(localCt);
        // return await task.ConfigureAwait(false);
        return await context.Blogs.FirstAsync(localCt).ConfigureAwait(false);
    }
}

Stack traces


Verbose output

> dotnet ef dbcontext optimize --output-dir Generated --nativeaot --precompile-queries --verbose
Using project '/workspaces/ef-play/confawait/confawait.csproj'.
Using startup project '/workspaces/ef-play/confawait/confawait.csproj'.
dotnet msbuild /getProperty:ProjectName /getProperty:AssemblyName /getProperty:DesignAssembly /getProperty:Language /getProperty:OutputPath /getProperty:PlatformTarget /getProperty:ProjectAssetsFile /getProperty:ProjectDir /getProperty:RootNamespace /getProperty:RuntimeFrameworkVersion /getProperty:TargetFileName /getProperty:TargetFrameworkMoniker /getProperty:Nullable /getProperty:TargetFramework /getProperty:TargetPlatformIdentifier /getProperty:Platform /t:ResolvePackageAssets /getItem:RuntimeCopyLocalItems /workspaces/ef-play/confawait/confawait.csproj
dotnet msbuild /getProperty:ProjectName /getProperty:AssemblyName /getProperty:DesignAssembly /getProperty:Language /getProperty:OutputPath /getProperty:PlatformTarget /getProperty:ProjectAssetsFile /getProperty:ProjectDir /getProperty:RootNamespace /getProperty:RuntimeFrameworkVersion /getProperty:TargetFileName /getProperty:TargetFrameworkMoniker /getProperty:Nullable /getProperty:TargetFramework /getProperty:TargetPlatformIdentifier /getProperty:Platform /t:ResolvePackageAssets /getItem:RuntimeCopyLocalItems /workspaces/ef-play/confawait/confawait.csproj
Build started...
dotnet build /workspaces/ef-play/confawait/confawait.csproj /verbosity:quiet /nologo /p:PublishAot=false /p:EFOptimizeContext=false

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:04.87

Build succeeded.
dotnet exec --depsfile /workspaces/ef-play/confawait/bin/Debug/net11.0/confawait.deps.json --additionalprobingpath /root/.nuget/packages --runtimeconfig /workspaces/ef-play/confawait/bin/Debug/net11.0/confawait.runtimeconfig.json /root/.dotnet/tools/.store/dotnet-ef/11.0.0-preview.1.26104.118/dotnet-ef/11.0.0-preview.1.26104.118/tools/net10.0/any/tools/net10.0/any/ef.dll dbcontext optimize --output-dir Generated --nativeaot --precompile-queries --assembly /workspaces/ef-play/confawait/bin/Debug/net11.0/confawait.dll --project /workspaces/ef-play/confawait/confawait.csproj --startup-assembly /workspaces/ef-play/confawait/bin/Debug/net11.0/confawait.dll --startup-project /workspaces/ef-play/confawait/confawait.csproj --project-dir /workspaces/ef-play/confawait/ --root-namespace confawait --language C# --framework net11.0 --design-assembly /root/.nuget/packages/microsoft.entityframeworkcore.design/11.0.0-preview.2.26159.112/lib/net11.0/Microsoft.EntityFrameworkCore.Design.dll --nullable --working-dir /workspaces/ef-play/confawait --verbose
Query precompilation is an experimental feature and should be used with caution.
NativeAOT support is experimental and can change in the future.
Using assembly 'confawait'.
Using startup assembly 'confawait'.
Using application base '/workspaces/ef-play/confawait/bin/Debug/net11.0'.
Using working directory '/workspaces/ef-play/confawait'.
Using root namespace 'confawait'.
Using project directory '/workspaces/ef-play/confawait/'.
Remaining arguments: .
Finding DbContext classes...
Using environment 'Development'.
Finding IDesignTimeDbContextFactory implementations...
Finding DbContext classes in the project...
Found DbContext 'Context'.
Finding application service provider in assembly 'confawait'...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Using context 'Context'.
Finding design-time services referenced by assembly 'confawait'...
Finding design-time services referenced by assembly 'confawait'...
No referenced design-time services were found.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.Sqlite'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.Sqlite'.
Finding IDesignTimeServices implementations in assembly 'confawait'...
No design-time services were found.
Successfully generated a compiled model, it will be discovered automatically, but you can also call 'options.UseModel(ContextModel.Instance)'. Run this command again when the model is modified.
'Context' disposed.
System.InvalidOperationException: Query precompilation failed with errors:
QueryPrecompilationError { SyntaxNode = context.Blogs.FirstAsync(localCt), Exception = System.InvalidOperationException: Encountered unknown identifier name 'localCt', which doesn't correspond to a lambda parameter or captured variable
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }

   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.PrecompileQueries(String outputDir, DbContext context, String suffix, IServiceProvider services, IReadOnlyDictionary`2 memberAccessReplacements, ISet`1 generatedFileNames)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String suffix, Boolean scaffoldModel, Boolean precompileQueries, DbContext context, Boolean optimizeAllInAssembly, Boolean nativeAot, List`1 generatedFiles, HashSet`1 generatedFileNames)
   at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.Optimize(String outputDir, String modelNamespace, String contextTypeName, String suffix, Boolean scaffoldModel, Boolean precompileQueries, Boolean nativeAot)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeContextImpl(String outputDir, String modelNamespace, String contextType, String suffix, Boolean scaffoldModel, Boolean precompileQueries, Boolean nativeAot)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OptimizeContext.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Query precompilation failed with errors:
QueryPrecompilationError { SyntaxNode = context.Blogs.FirstAsync(localCt), Exception = System.InvalidOperationException: Encountered unknown identifier name 'localCt', which doesn't correspond to a lambda parameter or captured variable
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitIdentifierName(IdentifierNameSyntax identifierName)
   at Microsoft.CodeAnalysis.CSharp.Syntax.IdentifierNameSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitArgument(ArgumentSyntax argument, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node, Type expectedType)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.VisitInvocationExpression(InvocationExpressionSyntax invocation)
   at Microsoft.CodeAnalysis.CSharp.Syntax.InvocationExpressionSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor`1.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Visit(SyntaxNode node)
   at Microsoft.EntityFrameworkCore.Query.Internal.CSharpToLinqTranslator.Translate(SyntaxNode node, SemanticModel semanticModel)
   at Microsoft.EntityFrameworkCore.Query.Internal.PrecompiledQueryCodeGenerator.ProcessSyntaxTree(SyntaxTree syntaxTree, SemanticModel semanticModel, IReadOnlyList`1 locatedQueries, List`1 precompilationErrors, String suffix, ISet`1 generatedFileNames, CancellationToken cancellationToken) }

EF Core version

10.0.3, 11.0.0-preview.2.26159.112

Database provider

Microsoft.EntityFrameworkCore.Sqlite

Target framework

.NET 10, .NET 11

Operating system

Ubuntu 24.04.4 LTS

IDE

No response

Activity

  1. roji commented on Mar 20, 2026

    @roji
    Member

    Thanks for raising this. I'm putting on the backlog as we're looking at better ways to support NativeAOT, but at some point we'll do a push and I'll take a look at fixing this.

  2. added this to the Backlog milestone on Mar 20, 2026
  3. added theissue type on Mar 20, 2026
  4. nurullahturkoglu commented on Oct 17, 2026

    @nurullahturkoglu
    Contributor

    I'd like to fix this if it's open for a community PR, unless you'd rather keep it for the NativeAOT push.

    The failure comes from Roslyn's data flow analysis. CSharpToLinqTranslator.Translate gets the captured variables from AnalyzeDataFlow(node), but when the query is the receiver of an instance method call, the result has Succeeded == false and an empty DataFlowsIn. The translator doesn't check Succeeded, so localCt ends up as an unknown identifier.

    On the Roslyn side, AbstractFlowPass.VisitCall walks a chain of receiver calls in a loop without visiting each receiver, so the region is never entered.

    Async isn't required. context.Blogs.Count(b => b.Id == id).ToString() and context.Blogs.Where(b => b.Id == id).ToList().Contains(blog) fail the same way, while extension method calls and property accesses on the result work.

    My plan is to retry the analysis on the parent expression when it fails, moving up until it succeeds. The parent's DataFlowsIn includes the query's variables, and any extra ones don't matter because the translator only looks up identifiers inside the query.

    I have this working locally with two new tests in PrecompiledQueryRelationalTestBase: the ConfigureAwait case from this issue and the sync ToString() case. Both fail on main with the unknown identifier error and pass with the change, and EFCore.Design.Tests and the precompiled SQLite tests still pass. Does that sound OK? If so I'll open a PR.

  5. added a commit that references this issue on Oct 22, 2026
    4317e84
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions