aspire icon indicating copy to clipboard operation
aspire copied to clipboard

watch-mode broken on apphost with azure functions

Open earloc opened this issue 1 month ago • 1 comments

Is there an existing issue for this?

  • [x] I have searched the existing issues

Describe the bug

When trying to run an apphost in watch-mode, which includes an azure function project, either via

  1. aspire run, when "features": { "defaultWatchEnabled": true }
  2. Start debugging in vs-code on the default aphost-project (aspire-extension installed)
  3. dotnet watch

the project won't start - respectively crashes shortly after startup.

This breaks our watch-loop for our frontend, as we rely on multiple things to be working in the functions-project. Workarounds like specified in #9142 either do not apply, or stopped working after our upgrade fom

  • net9 -> net10
  • aspire 9.5 -> aspire 13

Expected Behavior

Running the apphost in watch-mode, doesn't crash an included azure functions project.

Steps To Reproduce

  1. clone the aspire-samples (dca86f21fc3cf0c04f54ff38dc93a5558c852e33)
  2. run cd/samples/AspireWithAzureFunctions
  3. run aspire update
  4. run either of one:
  • cd ImageGallery.AppHost & dotnet watch
  • aspire config set defaultWatchEnabled true & aspire run
  • vs-code: Aspire: launch default apphost

Observe the functions project crashing

Exceptions (if any)

An unhandled exception of type 'System.InvalidOperationException' occurred in System.Private.CoreLib.dll: 'Configuration is missing the 'HostEndpoint' information. Please ensure an entry with the key 'Functions:Worker:HostEndpoint' is present in your configuration.'
   at Microsoft.Extensions.DependencyInjection.GrpcServiceCollectionExtensions.GetFunctionsHostGrpcUri(IConfiguration configuration) in D:\a\_work\1\s\src\DotNetWorker.Grpc\GrpcServiceCollectionExtensions.cs:line 83
   at Microsoft.Extensions.DependencyInjection.GrpcServiceCollectionExtensions.GrpcWorkerStartupOptionsSetup.Configure(GrpcWorkerStartupOptions options) in D:\a\_work\1\s\src\DotNetWorker.Grpc\GrpcServiceCollectionExtensions.cs:line 98
   at Microsoft.Extensions.Options.OptionsFactory`1.Create(String name)
   at Microsoft.Extensions.Options.UnnamedOptionsManager`1.get_Value()
   at Microsoft.Azure.Functions.Worker.Grpc.GrpcWorkerClientFactory..ctor(GrpcHostChannel outputChannel, IOptions`1 startupOptions) in D:\a\_work\1\s\src\DotNetWorker.Grpc\GrpcWorkerClientFactory.cs:line 29
   at System.Reflection.MethodBaseInvoker.InvokeWithFewArgs(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBaseInvoker.cs:line 136
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) in /_/src/runtime/src/libraries/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs:line 157
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitIEnumerable(IEnumerableCallSite enumerableCallSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitRootCache(ServiceCallSite callSite, RuntimeResolverContext context)
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(ServiceIdentifier serviceIdentifier)
   at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory) in /_/src/runtime/src/libraries/System.Collections.Concurrent/src/System/Collections/Concurrent/ConcurrentDictionary.cs:line 1201
   at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) in /_/src/runtime/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs:line 45
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) in /_/src/runtime/src/libraries/Microsoft.Extensions.DependencyInjection.Abstractions/src/ServiceProviderServiceExtensions.cs:line 65
   at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__14.MoveNext()
   at Microsoft.Extensions.Hosting.Internal.Host.<StartAsync>d__14.MoveNext()
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 67
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.<RunAsync>d__4.MoveNext() in /_/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 79
   at Microsoft.Extensions.Hosting.HostingAbstractionsHostExtensions.Run(IHost host) in /_/src/runtime/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/HostingAbstractionsHostExtensions.cs:line 53
   at Program.<Main>$(String[] args) in /Users/<user>/<path>/dotnet/aspire-samples/samples/AspireWithAzureFunctions/ImageGallery.Functions/AppHost.cs:line 13

```

### .NET Version info

# dotnet
.NET SDK:
 Version:           10.0.100
 Commit:            b0f34d51fc
 Workload version:  10.0.100-manifests.4c0ca8ba
 MSBuild version:   18.0.2+b0f34d51f

Runtime Environment:
 OS Name:     Mac OS X
 OS Version:  26.1
 OS Platform: Darwin
 RID:         osx-arm64
 Base Path:   /Users/earloc/.dotnet/sdk/10.0.100/

.NET workloads installed:
There are no installed workloads to display.
Configured to use workload sets when installing new manifests.
No workload sets are installed. Run "dotnet workload restore" to install a workload set.

Host:
  Version:      10.0.0
  Architecture: arm64
  Commit:       b0f34d51fc

.NET SDKs installed:
  9.0.307 [/Users/<user>/.dotnet/sdk]
  10.0.100 [/Users/<user>/.dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 9.0.11 [/Users/<user>/.dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 10.0.0 [/Users/<user>.dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 9.0.11 [/Users/<user>/.dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 10.0.0 [/Users/<user>/.dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
  None


# aspire --version
13.0.0+7512c2944094a58904b6c803aa824c4a4ce42e11



# func --help

Azure Functions Core Tools
Core Tools Version:       4.4.1+e4b8a4bdc8fd3b73143908be867f029865b74647 (64-bit)
Function Runtime Version: 4.1043.200.25453



### Anything else?

If it would be working, all the recently added enhancments are really promising. Keep up the good work!

For now, we'd be fine if functions would just Start normally, w/o watch-Mode enabled (despite this would be nice, though 🫠) 

earloc avatar Nov 14 '25 22:11 earloc

For now, to get rid of the most pressing road block, we're gonna run functions as a container, when we detect watch-mode.

This should at least re-enable a tighter dev-loop for working on frontend stuff.

Building this around AddDockerFile, so #969 might have helped here alot. (especially, since functions can be quite some beast to tame, when running as a container).

earloc avatar Nov 15 '25 13:11 earloc

Can we have an update in this? Especially since this used to work in 9.5?

earloc avatar Nov 26 '25 05:11 earloc

@earloc , did running funcions as container solve the issue for you? if so can you share how you do the AddDockerFile with function? We might meet similar issue and want to see if you find a workaround for it.

chuanboz avatar Nov 27 '25 08:11 chuanboz

@chuanboz Would need some time to port it somewhere, maybe onto the official samples.

Will come back when I found the time.

earloc avatar Nov 27 '25 15:11 earloc

@chuanboz I tried to give the core idea / basic gist of it over at my fork of the official aspire-samples. In my original workaround I used a full blown container-file, but this approach outlined here seems to work just as fine, at least for this simple sample.

earloc avatar Nov 30 '25 18:11 earloc

thanks @earloc to share the detail samples, i learned from you how to build the container at runtime.

chuanboz avatar Dec 01 '25 01:12 chuanboz