{"record":{"id":"bf43908e4ac34f52","repo":"microsoft/aspire","slug":"resourcereadyevent-was-published-for-the-sqlserver-name","errorCode":null,"errorMessage":"ResourceReadyEvent was published for the '{sqlServer.Name}' resource but the connection string was null.","messagePattern":"ResourceReadyEvent was published for the '(.+?)' resource but the connection string was null\\.","errorType":"exception","errorClass":"DistributedApplicationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.SqlServer/SqlServerBuilderExtensions.cs","lineNumber":77,"sourceCode":"                      .WithEnvironment(context =>\n                      {\n                          context.EnvironmentVariables[\"MSSQL_SA_PASSWORD\"] = sqlServer.PasswordParameter;\n                      })\n                      .WithHealthCheck(healthCheckKey)\n                      .OnConnectionStringAvailable(async (sqlServer, @event, ct) =>\n                      {\n                          connectionString = await sqlServer.GetConnectionStringAsync(ct).ConfigureAwait(false);\n\n                          if (connectionString == null)\n                          {\n                              throw new DistributedApplicationException($\"ConnectionStringAvailableEvent was published for the '{sqlServer.Name}' resource but the connection string was null.\");\n                          }\n                      })\n                      .OnResourceReady(async (sqlServer, @event, ct) =>\n                      {\n                          if (connectionString is null)\n                          {\n                              throw new DistributedApplicationException($\"ResourceReadyEvent was published for the '{sqlServer.Name}' resource but the connection string was null.\");\n                          }\n\n                          using var sqlConnection = new SqlConnection(connectionString);\n                          await sqlConnection.OpenAsync(ct).ConfigureAwait(false);\n\n                          if (sqlConnection.State != System.Data.ConnectionState.Open)\n                          {\n                              throw new InvalidOperationException($\"Could not open connection to '{sqlServer.Name}'\");\n                          }\n\n                          foreach (var sqlDatabase in sqlServer.DatabaseResources)\n                          {\n                              await CreateDatabaseAsync(sqlConnection, sqlDatabase, @event.Services, ct).ConfigureAwait(false);\n                          }\n                      });\n    }\n\n    /// <summary>","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.SqlServer/SqlServerBuilderExtensions.cs#L59-L95","documentation":"When the SQL Server resource signals ResourceReadyEvent, the integration expects the connection string captured in the earlier ConnectionStringAvailableEvent callback to be set. It opens a SqlConnection and creates any declared databases. If the connection string is still null at ResourceReady time, the ordering guarantee was violated and the integration throws DistributedApplicationException.","triggerScenarios":"OnResourceReady executes while the local connectionString variable is null: the ConnectionStringAvailable handler either never ran, threw before assigning (see the sibling null-check error), or event ordering was disturbed so ResourceReady fires without a prior ConnectionStringAvailable — typically caused by custom eventing, resource replacement, or an integration version regression.","commonSituations":"Custom AppHost code subscribing/reordering lifecycle events on the SQL Server resource; a resource builder or model transformation that re-created the resource and lost the earlier event wiring; debugging scenarios where the ConnectionStringAvailable callback failed silently earlier.","solutions":["Check the dashboard/logs for a failure in the ConnectionStringAvailable step of this same resource; fixing that failure restores the expected ordering and removes this error.","Do not replace or re-create the SqlServerServerResource builder/resource after AddSqlServer; always chain on the returned IResourceBuilder so its event handlers stay attached.","Remove custom event subscriptions that could preempt or suppress the integration's OnConnectionStringAvailable handler for this resource.","Update Aspire.Hosting.SqlServer if you suspect an eventing ordering regression; reproduce with a minimal AppHost to confirm."],"exampleFix":"// before\nvar sqlServer = builder.AddSqlServer(\"sql\");\nvar rebuilt = builder.CreateResourceBuilder(sqlServer.Resource); // detaches original event wiring\nrebuilt.WithReference(...);\n\n// after\nvar sqlServer = builder.AddSqlServer(\"sql\");\nsqlServer.WithReference(...); // chain on the original builder, preserving lifecycle event wiring","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    // start/await resource lifecycle\n}\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"ResourceReadyEvent was published\"))\n{\n    // lifecycle ordering violated: check whether ConnectionStringAvailable handling failed earlier for this resource\n}","preventionTips":["Treat this error as a symptom: fix the earlier ConnectionStringAvailable failure that left the connection string null.","Do not subscribe custom lifecycle events that reorder or suppress the integration's handlers on the SQL Server resource.","Always use the builder instance returned by AddSqlServer for subsequent configuration.","After upgrading Aspire packages, verify resource startup end-to-end in run mode to catch eventing changes early."],"tags":["sqlserver","connection-string","eventing","lifecycle"],"backgroundTag":"internal-invariant-violation","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}