microsoft/aspire · error · DistributedApplicationException

Stopped waiting for resource

Error message

Stopped waiting for resource '{resourceName}' to become healthy because it failed to start.

What it means

Thrown by WaitForResourceHealthyAsync when a resource being waited on reaches the end of its start attempt in a state other than Healthy (e.g. FailedToStart, Exited, Finished). The library stops waiting instead of blocking indefinitely and surfaces a DistributedApplicationException so the app model fails fast with a clear reason.

Solutions

  1. Inspect the resource's logs in the Aspire dashboard to find why it failed to start (missing env var, bad image, crash).
  2. Fix the resource configuration (image tag, connection string, bindings) so it can become healthy.
  3. If the resource legitimately exits after work (batch job), use WaitForCompletion with an expected exit code instead of WaitForResourceHealthy.
  4. Ensure required dependencies are ordered with WithReference so they start before the failing resource.
  5. Wrap the AppHost startup/wait in try-catch on DistributedApplicationException when failure is an expected runtime condition.

Example fix

// before
builder.AddProject<Projects.Api>("api")
    .WaitForResourceHealthy("db");

// after (db is a one-shot migrator job, so wait for successful completion instead)
builder.AddProject<Projects.Api>("api")
    .WaitForCompletion("db", exitCode: 0);
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the dependency exposes health checks before waiting on 'healthy'
if (resourceBuilder.Resource is IResourceWithHealthCheck)
{
    builder.WaitForResourceHealthy(resourceBuilder.Resource.Name);
}

Try / catch

try
{
    await app.StartAsync();
}
catch (DistributedApplicationException ex) when (ex.Message.Contains("failed to start"))
{
    logger.LogError(ex, "Dependency failed to start; check dashboard logs.");
}

Prevention

When it happens

Trigger: Calling builder.CreateResourceBuilder(resource).WaitForResourceHealthy(name) (or the public WaitForResourceHealthyAsync) while the target resource transitions to FailedToStart, Exited, Finished, or RuntimeUnhealthy instead of Healthy.

Common situations: Container image cannot be pulled or crashes at startup; connection strings or env vars invalid so the child app dies during boot; dependency database not ready so the resource's own startup health checks fail; port conflicts.

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/d184264e0f6c7a21. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting/ApplicationModel/ResourceNotificationService.cs:266

            var appModel = _serviceProvider.GetService<DistributedApplicationModel>();
            if (appModel is not null && !appModel.Resources.Any(r => string.Equals(r.Name, resourceName, StringComparisons.ResourceName)))
            {
                _logger.LogError("Stopped waiting for resource '{ResourceName}' to become healthy because it does not exist in the application model.", resourceName);
                throw new DistributedApplicationException($"Stopped waiting for resource '{resourceName}' to become healthy because it does not exist in the application model.");
            }
        }

        var resourceEvent = await WaitForResourceCoreAsync(
            resourceName,
            re => ShouldYieldHealthyWait(waitBehavior, re.Snapshot),
            $"Resource '{resourceName}' failed to become healthy before the operation was cancelled.",
            waitCondition: "healthy",
            cancellationToken: cancellationToken).ConfigureAwait(false);

        if (resourceEvent.Snapshot.HealthStatus != HealthStatus.Healthy)
        {
            _logger.LogError("Stopped waiting for resource '{ResourceName}' to become healthy because it failed to start.", resourceName);
            throw new DistributedApplicationException($"Stopped waiting for resource '{resourceName}' to become healthy because it failed to start.");
        }

        // Now wait for the resource ready event to be executed (matching behavior of WaitUntilHealthyAsync).
        _logger.LogDebug("Waiting for resource ready to execute for '{ResourceName}'.", resourceName);
        resourceEvent = await WaitForResourceCoreAsync(
            resourceName,
            re => re.ResourceId == resourceEvent.ResourceId && re.Snapshot.ResourceReadyEvent is not null,
            $"Resource '{resourceName}' failed to execute the resource ready event before the operation was cancelled.",
            waitCondition: "resource_ready",
            cancellationToken: cancellationToken).ConfigureAwait(false);

        // Observe the result of the resource ready event task
        await resourceEvent.Snapshot.ResourceReadyEvent!.EventTask.WaitAsync(cancellationToken).ConfigureAwait(false);

        _logger.LogDebug("Finished waiting for resource '{ResourceName}'.", resourceName);

        return resourceEvent;
    }

View on GitHub (pinned to 25830f84bd)