microsoft/aspire · error · DistributedApplicationException
Stopped waiting for resource
Error message
Stopped waiting for resource '{target.DisplayName}' to become healthy because it failed to start. What it means
When waiting for a resource to become healthy (WaitForResourceAsync with status 'healthy'), the wait ended because the resource reached an unavailable/failed state (WaitBehavior.StopOnResourceUnavailable). Since the final HealthStatus was not Healthy, a DistributedApplicationException is thrown reporting the resource failed to start rather than becoming healthy.
Solutions
- Inspect the resource state/logs in the Aspire dashboard to find the startup failure cause.
- Fix the underlying resource startup error (image name, environment variables, connection strings, command).
- Verify health-check endpoints/annotations (WithHealthCheck) are reachable and correctly configured.
- Catch DistributedApplicationException in the wait caller and handle the failure gracefully.
- Re-run the wait after the resource configuration is corrected.
Example fix
// before
var resp = await rpc.WaitForResourceAsync(new WaitForResourceRequest { ResourceName = "pg", Status = "healthy", TimeoutSeconds = 60 });
// after
try
{
var resp = await rpc.WaitForResourceAsync(new WaitForResourceRequest { ResourceName = "pg", Status = "healthy", TimeoutSeconds = 60 });
}
catch (DistributedApplicationException ex)
{
logger.LogError(ex, "Resource failed to start; check dashboard logs.");
} Defensive patterns
Strategy: try-catch
Try / catch
try { var resp = await rpc.WaitForResourceAsync(new WaitForResourceRequest { ResourceName = name, Status = "healthy", TimeoutSeconds = 120 }); }
catch (DistributedApplicationException ex) { logger.LogError(ex, "Resource '{Name}' failed to start; inspect dashboard logs.", name); } Prevention
- Fix resource startup config (images, env vars, connection strings) before waiting on health.
- Verify health-check annotations point at reachable endpoints.
- Handle DistributedApplicationException as an expected failure path in wait automation.
- Check the dashboard's resource state/logs for the first failure cause.
When it happens
Trigger: WaitForResourceAsync(request.Status="healthy") where the target resource's snapshot yields the healthy wait with a non-Healthy health status — e.g. resource entered FailedToStart, RuntimeUnhealthy, or Disabled state before becoming Healthy.
Common situations: Container image pull failures or bad image tags; app crashes during startup (missing env vars, bad connection strings); health-check endpoints not responding; resource disabled by configuration.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/c8a6eebd5b0f15a9.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting/Backchannel/AuxiliaryBackchannelRpcTarget.cs:687
}
catch (DistributedApplicationException ex)
{
return new WaitForResourceResponse { Success = false, ErrorMessage = ex.Message };
}
}
private static async Task<WaitForResourceResponse> WaitForHealthyAsync(ResourceNotificationService notificationService, WaitResourceTarget target, CancellationToken cancellationToken)
{
var resourceEvent = await WaitForResourceEventAsync(
notificationService,
target,
re => ResourceNotificationService.ShouldYieldHealthyWait(WaitBehavior.StopOnResourceUnavailable, re.Snapshot),
$"Resource '{target.DisplayName}' failed to become healthy before the operation was cancelled.",
cancellationToken).ConfigureAwait(false);
if (resourceEvent.Snapshot.HealthStatus != HealthStatus.Healthy)
{
throw new DistributedApplicationException($"Stopped waiting for resource '{target.DisplayName}' to become healthy because it failed to start.");
}
resourceEvent = await WaitForResourceEventAsync(
notificationService,
new WaitResourceTarget(target.DisplayName, resourceEvent.ResourceId, null),
re => re.Snapshot.ResourceReadyEvent is not null,
$"Resource '{target.DisplayName}' failed to execute the resource ready event before the operation was cancelled.",
cancellationToken).ConfigureAwait(false);
await resourceEvent.Snapshot.ResourceReadyEvent!.EventTask.WaitAsync(cancellationToken).ConfigureAwait(false);
return new WaitForResourceResponse
{
Success = true,
State = resourceEvent.Snapshot.State?.Text,
HealthStatus = resourceEvent.Snapshot.HealthStatus?.ToString()
};
}View on GitHub (pinned to 25830f84bd)