Describe the bug
In run mode, an AppHost that combines Azure resources with a Dapr sidecar crashes at startup before anything boots.
When you call AddAzureContainerAppEnvironment, the Azure hosting integration registers an azure-prepare-resources before-start step. To discover Azure role-assignment references, that step walks the compute resources and eagerly fires their EnvironmentCallbackAnnotation callbacks — before DCP has allocated any endpoints.
The CommunityToolkit Dapr lifecycle hook adds an EnvironmentCallbackAnnotation to the app resource that eagerly reads the auto-generated <name>-dapr-cli sidecar's http/grpc endpoint .Port. Because the endpoints are not yet allocated when the Azure discovery walk runs, the read throws and the whole AppHost dies (exit code 134):
System.InvalidOperationException: The endpoint `http` is not allocated for the resource `<name>-dapr-cli`.
Root cause is in this repo:
src/CommunityToolkit.Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs, lines 243-244 (inside the EnvironmentCallbackAnnotation added to the app resource at lines 231-249):
context.EnvironmentVariables.TryAdd("DAPR_HTTP_PORT", http.Port.ToString(CultureInfo.InvariantCulture));
context.EnvironmentVariables.TryAdd("DAPR_GRPC_PORT", grpc.Port.ToString(CultureInfo.InvariantCulture));
http.Port / grpc.Port force resolution of the allocated port and throw when it hasn't been allocated yet. The two lines just below (DAPR_GRPC_ENDPOINT / DAPR_HTTP_ENDPOINT, lines 246-247) add the EndpointReference object directly, so they are deferred and do NOT throw — this is exactly the split that needs fixing.
The upstream tracking issue microsoft/aspire#18242 was closed as by-design: Aspire intends the discovery walk to collect references without resolving them, and env callbacks are expected to supply values as deferred references. So the fix belongs here, in CommunityToolkit.Aspire.Hosting.Dapr.
Regression
Started failing between toolkit 13.3.5 → 13.4.4. The eager .Port read is long-standing, but an upstream multi-network endpoint-allocation timing change flipped it from a latent issue into a hard crash in run mode when Azure resources are present. The fix lives in CommunityToolkit.Aspire.Hosting.Dapr.
Steps to reproduce
1. .NET 10 AppHost. Reference CommunityToolkit.Aspire.Hosting.Dapr (13.x) and an
Aspire.Hosting.Azure.* integration.
2. Use AddAzureContainerAppEnvironment, add at least one real Azure resource, and add
a worker with a Dapr sidecar via .WithDaprSidecar():
var builder = DistributedApplication.CreateBuilder(args);
builder.AddAzureContainerAppEnvironment("cae");
var storage = builder.AddAzureStorage("storage");
builder.AddProject<Projects.Worker>("worker")
.WithReference(storage)
.WithDaprSidecar();
using var app = builder.Build();
await app.StartAsync(); // throws in azure-prepare-resources
3. Run `aspire run`. Startup aborts (exit 134) before DCP allocates endpoints.
Observed stack trace (abridged):
System.InvalidOperationException: The endpoint `http` is not allocated for the resource `worker-dapr-cli`.
at Aspire.Hosting.ApplicationModel.EndpointReference.get_Port()
at CommunityToolkit.Aspire.Hosting.Dapr.DaprDistributedApplicationLifecycleHook
.<>c__DisplayClass.<OnBeforeStartAsync>b__() in
DaprDistributedApplicationLifecycleHook.cs:line 243
at Aspire.Hosting.ApplicationModel.ResourceExtensions
.GatherRawEnvironmentAndArgumentValuesAsync(...)
at Aspire.Hosting.Azure.AzureResourcePreparer.BuildRoleAssignmentAnnotations(...)
at Aspire.Hosting.Azure.AzureResourcePreparer.BeforeStartAsync(...) // azure-prepare-resources
Expected behavior
aspire run should discover Azure references without resolving endpoint values. The Dapr env callback must supply DAPR_HTTP_PORT / DAPR_GRPC_PORT as deferred reference expressions that are collected as raw references during the azure-prepare-resources walk and resolved later, after DCP allocates the endpoints. Startup should complete normally, and once endpoints are allocated the env vars must resolve to the correct proxy/host ports (e.g. DAPR_HTTP_PORT=3500, DAPR_GRPC_PORT=50001).
Screenshots
N/A
IDE and version
VS Code
IDE version
N/A
Nuget packages
CommunityToolkit.Aspire.Hosting.Dapr (13.x)
Aspire.Hosting.Azure.* (e.g. Aspire.Hosting.Azure.Storage)
.NET 10
Additional context
Root cause pinned to src/CommunityToolkit.Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs, lines 243-244.
Proposed fix — swap the eager .Port.ToString() for a deferred reference expression:
context.EnvironmentVariables.TryAdd("DAPR_HTTP_PORT", http.Property(EndpointProperty.Port));
context.EnvironmentVariables.TryAdd("DAPR_GRPC_PORT", grpc.Property(EndpointProperty.Port));
EndpointReference.Property(EndpointProperty.Port) returns an EndpointReferenceExpression (an IValueProvider / IManifestExpressionProvider) that the discovery walk collects as a raw reference without resolving — so it does not throw at before-start, and still resolves to the correct allocated proxy/host Port later. EndpointProperty is already in scope (used for the CLI args at line 281 as EndpointProperty.TargetPort).
Note on Port vs TargetPort: DAPR_HTTP_PORT / DAPR_GRPC_PORT are placed on the app resource and are consumed by the app to reach the sidecar's Dapr APIs, which in run mode go through the DCP-allocated proxy/host port — so EndpointProperty.Port is correct here. The --dapr-http-port / --dapr-grpc-port CLI flags on the <name>-dapr-cli resource use EndpointProperty.TargetPort because those tell the sidecar process which container-internal port to bind. Different consumer, different port.
This is the exact workaround the maintainer (@karolz-ms) confirmed on microsoft/aspire#18242. After the fix, using System.Globalization; (line 14) becomes unused and can be removed.
Related:
Help us help you
Yes, I'd like to be assigned to work on this item
Describe the bug
In run mode, an AppHost that combines Azure resources with a Dapr sidecar crashes at startup before anything boots.
When you call
AddAzureContainerAppEnvironment, the Azure hosting integration registers anazure-prepare-resourcesbefore-start step. To discover Azure role-assignment references, that step walks the compute resources and eagerly fires theirEnvironmentCallbackAnnotationcallbacks — before DCP has allocated any endpoints.The CommunityToolkit Dapr lifecycle hook adds an
EnvironmentCallbackAnnotationto the app resource that eagerly reads the auto-generated<name>-dapr-clisidecar'shttp/grpcendpoint.Port. Because the endpoints are not yet allocated when the Azure discovery walk runs, the read throws and the whole AppHost dies (exit code 134):Root cause is in this repo:
src/CommunityToolkit.Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs, lines 243-244 (inside theEnvironmentCallbackAnnotationadded to the app resource at lines 231-249):http.Port/grpc.Portforce resolution of the allocated port and throw when it hasn't been allocated yet. The two lines just below (DAPR_GRPC_ENDPOINT/DAPR_HTTP_ENDPOINT, lines 246-247) add theEndpointReferenceobject directly, so they are deferred and do NOT throw — this is exactly the split that needs fixing.The upstream tracking issue microsoft/aspire#18242 was closed as by-design: Aspire intends the discovery walk to collect references without resolving them, and env callbacks are expected to supply values as deferred references. So the fix belongs here, in
CommunityToolkit.Aspire.Hosting.Dapr.Regression
Started failing between toolkit 13.3.5 → 13.4.4. The eager
.Portread is long-standing, but an upstream multi-network endpoint-allocation timing change flipped it from a latent issue into a hard crash in run mode when Azure resources are present. The fix lives inCommunityToolkit.Aspire.Hosting.Dapr.Steps to reproduce
Expected behavior
aspire runshould discover Azure references without resolving endpoint values. The Dapr env callback must supplyDAPR_HTTP_PORT/DAPR_GRPC_PORTas deferred reference expressions that are collected as raw references during theazure-prepare-resourceswalk and resolved later, after DCP allocates the endpoints. Startup should complete normally, and once endpoints are allocated the env vars must resolve to the correct proxy/host ports (e.g.DAPR_HTTP_PORT=3500,DAPR_GRPC_PORT=50001).Screenshots
N/A
IDE and version
VS Code
IDE version
N/A
Nuget packages
Additional context
Root cause pinned to
src/CommunityToolkit.Aspire.Hosting.Dapr/DaprDistributedApplicationLifecycleHook.cs, lines 243-244.Proposed fix — swap the eager
.Port.ToString()for a deferred reference expression:EndpointReference.Property(EndpointProperty.Port)returns anEndpointReferenceExpression(anIValueProvider/IManifestExpressionProvider) that the discovery walk collects as a raw reference without resolving — so it does not throw at before-start, and still resolves to the correct allocated proxy/host Port later.EndpointPropertyis already in scope (used for the CLI args at line 281 asEndpointProperty.TargetPort).Note on Port vs TargetPort:
DAPR_HTTP_PORT/DAPR_GRPC_PORTare placed on the app resource and are consumed by the app to reach the sidecar's Dapr APIs, which in run mode go through the DCP-allocated proxy/host port — soEndpointProperty.Portis correct here. The--dapr-http-port/--dapr-grpc-portCLI flags on the<name>-dapr-cliresource useEndpointProperty.TargetPortbecause those tell the sidecar process which container-internal port to bind. Different consumer, different port.This is the exact workaround the maintainer (@karolz-ms) confirmed on microsoft/aspire#18242. After the fix,
using System.Globalization;(line 14) becomes unused and can be removed.Related:
src/CommunityToolkit.Aspire.Hosting.OpenTelemetryCollector/OpenTelemetryCollectorRoutingExtensions.cs:31. Out of scope for this issue.Help us help you
Yes, I'd like to be assigned to work on this item