microsoft/aspire · error · InvalidOperationException

Connection string is unavailable

Error message

Connection string is unavailable

What it means

AddSqlServer registers an ASP.NET health check that resolves the SQL Server connection string from a captured local variable. That variable is only populated later, when the ConnectionStringAvailableEvent fires during resource startup. If the health check executes before that event has run (or the event failed to set it), the lambda throws this InvalidOperationException.

Solutions

  1. Let the AppHost start the SQL Server resource and wait for it: reference the server from dependent resources via WithReference so they wait for availability instead of probing the health check early.
  2. If you see this during normal startup, check the dashboard/logs for an earlier failure in the resource's ConnectionStringAvailable lifecycle (e.g. container failed to start, endpoint allocation failed) and fix the root cause.
  3. Do not invoke the '{name}_check' health check from outside the AppHost's resource orchestration; it depends on Aspire eventing to populate the connection string.
  4. If the resource never becomes healthy, verify the SQL Server container image can start (ACCEPT_EULA=Y is set, license accepted, port not conflicting).
Defensive patterns

Strategy: validation

Validate before calling

// Ensure dependents reference the server so they wait for availability instead of probing early
var sql = builder.AddSqlServer("sql");
var api = builder.AddProject<Projects.Api>("api")
    .WithReference(sql)
    .WaitFor(sql); // avoids hitting the health check before the connection string exists

Try / catch

try
{
    await healthCheckService.CheckHealthAsync("sql_check");
}
catch (InvalidOperationException ex) when (ex.Message == "Connection string is unavailable")
{
    // treat as 'not ready yet'; retry after the resource reaches Running/Healthy
}

Prevention

When it happens

Trigger: The '{name}_check' health check runs while connectionString is still null: health checks executed before the SQL Server container started and published its connection string, or the OnConnectionStringAvailable callback did not run/complete (resource startup failed, event pipeline interrupted), or the health check is invoked in a context where the Aspire eventing never populated the connection string (e.g. running the health check outside normal AppHost orchestration).

Common situations: Health check probed by an external orchestrator/load balancer before the SQL Server resource is running; AppHost startup failure leaves the resource never reaching ConnectionStringAvailable; custom tooling invoking health checks against an AppHost where the resource is not started.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/5a46aa9d8eacddb0. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.SqlServer/SqlServerBuilderExtensions.cs:51

    /// <param name="password">The parameter used to provide the administrator password for the SQL Server resource. If <see langword="null"/> a random password will be generated.</param>
    /// <param name="port">The host port for the SQL Server.</param>
    /// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
    /// <ats-returns>The resource builder.</ats-returns>
    [AspireExport]
    public static IResourceBuilder<SqlServerServerResource> AddSqlServer(this IDistributedApplicationBuilder builder, [ResourceName] string name, IResourceBuilder<ParameterResource>? password = null, int? port = null)
    {
        ArgumentNullException.ThrowIfNull(builder);
        ArgumentException.ThrowIfNullOrEmpty(name);

        // The password must be at least 8 characters long and contain characters from three of the following four sets: Uppercase letters, Lowercase letters, Base 10 digits, and Symbols
        var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $"{name}-password", minLower: 1, minUpper: 1, minNumeric: 1);

        var sqlServer = new SqlServerServerResource(name, passwordParameter);

        string? connectionString = null;

        var healthCheckKey = $"{name}_check";
        builder.Services.AddHealthChecks().AddSqlServer(sp => connectionString ?? throw new InvalidOperationException("Connection string is unavailable"), name: healthCheckKey);

        return builder.AddResource(sqlServer)
                      .WithEndpoint(port: port, targetPort: 1433, name: SqlServerServerResource.PrimaryEndpointName)
                      .WithImage(SqlServerContainerImageTags.Image, SqlServerContainerImageTags.Tag)
                      .WithImageRegistry(SqlServerContainerImageTags.Registry)
                      .WithIconName("DatabaseMultiple")
                      .WithEnvironment("ACCEPT_EULA", "Y")
                      .WithEnvironment(context =>
                      {
                          context.EnvironmentVariables["MSSQL_SA_PASSWORD"] = sqlServer.PasswordParameter;
                      })
                      .WithHealthCheck(healthCheckKey)
                      .OnConnectionStringAvailable(async (sqlServer, @event, ct) =>
                      {
                          connectionString = await sqlServer.GetConnectionStringAsync(ct).ConfigureAwait(false);

                          if (connectionString == null)
                          {

View on GitHub (pinned to 25830f84bd)