microsoft/aspire · error · InvalidOperationException
Could not open connection to
Error message
Could not open connection to '{sqlServer.Name}' What it means
Aspire's AddSqlServer registers a callback that runs when the SQL Server container resource is healthy: it opens a real SqlConnection to the server and then creates any child database resources. This DistributedApplicationException is thrown when the connection could not reach the Open state despite OpenAsync not throwing, meaning the server is reachable at the socket level but not accepting/validating SQL logins.
Solutions
- Verify the container is fully started (check docker logs for 'SQL Server is now ready for client connections') before the callback runs
- Confirm the SA_PASSWORD / password parameter matches what the container was created with and satisfies SQL Server password policy
- Check the connection string host/port matches the container's actual assigned endpoint (use the resource's endpoint, not a hard-coded port)
- Try connecting manually with sqlcmd or a SQL client using the same connection string to see the underlying failure
- Add connection retry logic; transient states during container startup can produce a non-Open final state
Example fix
// before
var sqlserver = builder.AddSqlServer("sql").AddDatabase("db");
// after - ensure a stable, valid password and rely on resource wait
var sqlserver = builder.AddSqlServer("sql", password: builder.Configuration["SqlPassword"])
.WithLifetime(ContainerLifetime.Persistent)
.AddDatabase("db"); Defensive patterns
Strategy: validation
Validate before calling
// before relying on the resource, wait for health and verify connectivity
await app.ResourceNotifications.WaitForResourceHealthyAsync("sql");
var cs = await sqlDatabaseResource.ConnectionStringExpression.GetValueAsync(ct);
if (cs is null) throw new InvalidOperationException("Connection string not yet available");
using var conn = new SqlConnection(cs);
await conn.OpenAsync(ct); // surface the real auth/TLS error early Try / catch
try
{
await sqlConnection.OpenAsync(ct);
}
catch (SqlException ex)
{
// inspect ex.Number: 18456 = login failed, -1 = timeout/network
logger.LogError(ex, "SQL Server connection failed (error {Number})", ex.Number);
throw;
} Prevention
- Use WithLifetime(ContainerLifetime.Persistent) and wait for resource healthy before connecting
- Always set an explicit, policy-compliant SA password; never rely on defaults
- Use the resource's assigned endpoint instead of hard-coded ports
- Test the connection string manually with sqlcmd when the container starts failing
When it happens
Trigger: Calling builder.AddSqlServer(...).AddDatabase(...) and the health-check callback fires, SqlConnection.OpenAsync returns but State != Open — typically an authentication failure, TLS negotiation failure, or the server reported an error without raising during OpenAsync.
Common situations: Wrong or missing SA password / password not yet applied to the container; container listening but SQL Server still initializing after health check passed; TLS/cert trust issues between client and container; connection string referencing wrong host or port after endpoint remapping.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- Container resource name
- -32603
- Already connected to
- Anonymous volumes cannot be read-only.
- AppHost server process exited before the RPC connection…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/cd163c8ada1874aa.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.SqlServer/SqlServerBuilderExtensions.cs:85
if (connectionString == null)
{
throw new DistributedApplicationException($"ConnectionStringAvailableEvent was published for the '{sqlServer.Name}' resource but the connection string was null.");
}
})
.OnResourceReady(async (sqlServer, @event, ct) =>
{
if (connectionString is null)
{
throw new DistributedApplicationException($"ResourceReadyEvent was published for the '{sqlServer.Name}' resource but the connection string was null.");
}
using var sqlConnection = new SqlConnection(connectionString);
await sqlConnection.OpenAsync(ct).ConfigureAwait(false);
if (sqlConnection.State != System.Data.ConnectionState.Open)
{
throw new InvalidOperationException($"Could not open connection to '{sqlServer.Name}'");
}
foreach (var sqlDatabase in sqlServer.DatabaseResources)
{
await CreateDatabaseAsync(sqlConnection, sqlDatabase, @event.Services, ct).ConfigureAwait(false);
}
});
}
/// <summary>
/// Adds a SQL Server database to the application model. This is a child resource of a <see cref="SqlServerServerResource"/>.
/// </summary>
/// <ats-summary>Adds a SQL Server database resource</ats-summary>
/// <param name="builder">The SQL Server resource builders.</param>
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
/// <param name="databaseName">The name of the database. If not provided, this defaults to the same value as <paramref name="name"/>.</param>
/// <returns>A reference to the <see cref="IResourceBuilder{T}"/>.</returns>
/// <ats-returns>The resource builder.</ats-returns>View on GitHub (pinned to 25830f84bd)