MissingMethodException thrown in native AoT application using AddStandardResilienceHandler() with .NET 9 preview.2
martincostello opened this issue · comments
Description
I've been testing an application of mine which is a native AoT application deployed to AWS Lambda with .NET 9. As part of the testing I wanted to try out the new JsonSerializerOptions.AllowOutOfOrderMetadataProperties property to support using polymorphism with the JSON serialization for types used by the AWS Alexa skills API.
Having resolved an issue with getting that to work properly, I've run into a new issue where trying to resolve an HttpClient
with HttpClientFactory when AddStandardResilienceHandler()
has been associated with all instances causes a MissingMethodException
to be thrown (martincostello/alexa-london-travel#1116 (comment)).
System.MissingMethodException: Constructor on type 'Polly.Registry.ResiliencePipelineRegistryOptions`1[Microsoft.Extensions.Http.Resilience.Internal.HttpKey]' not found.
at System.Activator.CreateInstance[T]() + 0x88
at Microsoft.Extensions.Options.OptionsFactory`1.Create(String) + 0x38
at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value() + 0xbc
at Polly.PollyServiceCollectionExtensions.<>c__6`1.<AddResiliencePipelineRegistry>b__6_0(IServiceProvider serviceProvider) + 0x3c
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite, RuntimeResolverContext) + 0x1c
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite, RuntimeResolverContext) + 0x74
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite, TArgument) + 0xb8
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite, ServiceProviderEngineScope) + 0x34
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier) + 0x130\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier, ServiceProviderEngineScope) + 0x384
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider, Type) + 0xc8
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider) + 0x30
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite, RuntimeResolverContext) + 0x1c
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite, RuntimeResolverContext) + 0x74
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite, TArgument) + 0xb8
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite, ServiceProviderEngineScope) + 0x34
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier) + 0x130\n at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier, ServiceProviderEngineScope) + 0x384
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider, Type) + 0xc8\n at Microsoft.Extensions.DependencyInjection.ResilienceHttpClientBuilderExtensions.CreatePipelineSelector(IServiceProvider, String) + 0x48
at Microsoft.Extensions.DependencyInjection.ResilienceHttpClientBuilderExtensions.<>c__DisplayClass6_0.<AddResilienceHandler>b__0(IServiceProvider serviceProvider) + 0x20
at Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.<>c__DisplayClass3_0.<AddHttpMessageHandler>b__1(HttpMessageHandlerBuilder) + 0x24
at Microsoft.Extensions.Http.DefaultHttpClientFactory.<>c__DisplayClass17_0.<CreateHandlerEntry>g__Configure|0(HttpMessageHandlerBuilder) + 0x78
at Microsoft.Extensions.Http.MetricsFactoryHttpMessageHandlerFilter.<>c__DisplayClass2_0.<Configure>b__0(HttpMessageHandlerBuilder) + 0x28
at Microsoft.Extensions.Http.LoggingHttpMessageHandlerBuilderFilter.<>c__DisplayClass6_0.<Configure>b__0(HttpMessageHandlerBuilder) + 0x30
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandlerEntry(String) + 0x258\n at System.Lazy`1.ViaFactory(LazyThreadSafetyMode) + 0x50
--- End of stack trace from previous location ---
at System.Lazy`1.CreateValue() + 0xdc
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateHandler(String) + 0x58
at Microsoft.Extensions.Http.DefaultHttpClientFactory.CreateClient(String) + 0x2c
at Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.AddTransientHelper[TClient](IServiceProvider, IHttpClientBuilder) + 0x3c\n at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite, RuntimeResolverContext) + 0x1c
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite, RuntimeResolverContext) + 0x20
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite, TArgument) + 0x154
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite, RuntimeResolverContext) + 0x88
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitDisposeCache(ServiceCallSite, RuntimeResolverContext) + 0x20
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor`2.VisitCallSite(ServiceCallSite, TArgument) + 0x154
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite, ServiceProviderEngineScope) + 0x34
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier, ServiceProviderEngineScope) + 0x344
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider, Type) + 0xc8
at MartinCostello.LondonTravel.Skill.IntentFactory.Create(Intent) + 0x278
at MartinCostello.LondonTravel.Skill.AlexaSkill.<OnIntentAsync>d__5.MoveNext() + 0x38
--- End of stack trace from previous location ---
at MartinCostello.LondonTravel.Skill.FunctionHandler.<HandleRequestAsync>d__4.MoveNext() + 0x198
It could be that this is a trimmer issue (or something wrong in my code that wasn't wrong before), but as the Microsoft.Extensions.Http.Resilience.Internal.HttpKey
type is defined in this repo and removing the call to AddStandardResilienceHandler()
(see martincostello/alexa-london-travel@e3e7de1) fixes the issue, I figured this was the best first port of call.
Reproduction Steps
I'll try and create a branch with an easy-to-execute local repro later, but the code with the issue is at this commit: martincostello/alexa-london-travel@50eb0a2.
1. Clone martincostello/alexa-london-travel@75e5c8b
2. Run build.ps1
in the root directory of the repository.
- Clone https://github.com/martincostello/dotnet-extensions-5062-repro
- Run the following commands from the root of the repository:
dotnet publish ./artifacts/publish/dotnet-extensions-5062-repro/release/repro
Expected behavior
HttpClient
requests using resilience are correctly resolved from DI and work as expected.
Actual behavior
A MissingMethodException
is thrown from here:
Regression?
From .NET 8, yes.
Known Workarounds
None.
Configuration
- .NET SDK
9.0.100-preview.2.24157.14
- Microsoft.Extensions.Http.Resilience
9.0.0-preview.2.24157.4
Other information
No response
Whether it's a problem or not I don't know, but I tried to restore the functionality by adding the following to my project file and I get these errors:
<PropertyGroup>
<TrimmerSingleWarn>false</TrimmerSingleWarn>
</PropertyGroup>
<ItemGroup>
<TrimmerRootAssembly Include="Microsoft.Extensions.Http.Resilience" />
</ItemGroup>
LondonTravel.Skill failed with errors (40.5s) → artifacts\bin\LondonTravel.Skill\release\LondonTravel.Skill.dll
ILC : Trim analysis error IL2026: Microsoft.Extensions.Http.Resilience.WeightedGroupsRoutingOptions.Groups: Using member 'System.ComponentModel.DataAnnotations.LengthAttribute.LengthAttribute(Int32,Int32)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Uses reflection to get the 'Count' property on types that don't implement ICollection. This 'Count' property may be trimmed. Ensure it is preserved. [C:\Coding\martincostello\alexa-london-travel\src\LondonTravel.Skill\LondonTravel.Skill.csproj]
ILC : Trim analysis error IL2026: Microsoft.Extensions.Http.Resilience.WeightedGroupsRoutingOptions.Groups: Using member 'System.ComponentModel.DataAnnotations.LengthAttribute.LengthAttribute(Int32,Int32)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Uses reflection to get the 'Count' property on types that don't implement ICollection. This 'Count' property may be trimmed. Ensure it is preserved. [C:\Coding\martincostello\alexa-london-travel\src\LondonTravel.Skill\LondonTravel.Skill.csproj]
ILC : Trim analysis error IL2026: Microsoft.Extensions.Http.Resilience.UriEndpointGroup.Endpoints: Using member 'System.ComponentModel.DataAnnotations.LengthAttribute.LengthAttribute(Int32,Int32)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Uses reflection to get the 'Count' property on types that don't implement ICollection. This 'Count' property may be trimmed. Ensure it is preserved. [C:\Coding\martincostello\alexa-london-travel\src\LondonTravel.Skill\LondonTravel.Skill.csproj]
ILC : Trim analysis error IL2026: Microsoft.Extensions.Http.Resilience.UriEndpointGroup.Endpoints: Using member 'System.ComponentModel.DataAnnotations.LengthAttribute.LengthAttribute(Int32,Int32)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Uses reflection to get the 'Count' property on types that don't implement ICollection. This 'Count' property may be trimmed. Ensure it is preserved. [C:\Coding\martincostello\alexa-london-travel\src\LondonTravel.Skill\LondonTravel.Skill.csproj]
ILC : Trim analysis error IL2026: Microsoft.Extensions.Http.Resilience.OrderedGroupsRoutingOptions.Groups: Using member 'System.ComponentModel.DataAnnotations.LengthAttribute.LengthAttribute(Int32,Int32)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Uses reflection to get the 'Count' property on types that don't implement ICollection. This 'Count' property may be trimmed. Ensure it is preserved. [C:\Coding\martincostello\alexa-london-travel\src\LondonTravel.Skill\LondonTravel.Skill.csproj]
ILC : Trim analysis error IL2026: Microsoft.Extensions.Http.Resilience.OrderedGroupsRoutingOptions.Groups: Using member 'System.ComponentModel.DataAnnotations.LengthAttribute.LengthAttribute(Int32,Int32)' which has 'RequiresUnreferencedCodeAttribute' can break functionality when trimming application code. Uses reflection to get the 'Count' property on types that don't implement ICollection. This 'Count' property may be trimmed. Ensure it is preserved. [C:\Coding\martincostello\alexa-london-travel\src\LondonTravel.Skill\LondonTravel.Skill.csproj]
Looking at the code, the warnings are being suppressed using pragmas rather than attributes, so the trimmer can't reason about the intentional suppressions.
I've also tried the following, but that doesn't seem to be working either:
<ItemGroup>
<TrimmerRootDescriptor Include="TrimmerRoots.xml" />
</ItemGroup>
<linker>
<assembly fullname="Microsoft.Extensions.Http.Resilience">
<type fullname="Microsoft.Extensions.Http.Resilience.Internal.HttpKey" preserve="all" />
</assembly>
<assembly fullname="Polly.Core">
<type fullname="Polly.Registry.ResiliencePipelineRegistryOptions`1" preserve="all" />
</assembly>
</linker>
Still observing this issue with .NET 9 preview 3.
I've been able to reproduce this outside of my deployed AWS Lambda function using the new AoT support in MSTest here: martincostello/alexa-london-travel#1157
Minimal repro added here: https://github.com/martincostello/dotnet-extensions-5062-repro
@iliar-turdushev could you please have a look?