{"record":{"id":"1a47cbc479a13c03","repo":"microsoft/aspire","slug":"connectionstringavailableevent-was-published-for-the-1a47cb","errorCode":null,"errorMessage":"ConnectionStringAvailableEvent was published for the '{sqlServer.Name}' resource but the connection string was null.","messagePattern":"ConnectionStringAvailableEvent 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":70,"sourceCode":"\n        return builder.AddResource(sqlServer)\n                      .WithEndpoint(port: port, targetPort: 1433, name: SqlServerServerResource.PrimaryEndpointName)\n                      .WithImage(SqlServerContainerImageTags.Image, SqlServerContainerImageTags.Tag)\n                      .WithImageRegistry(SqlServerContainerImageTags.Registry)\n                      .WithIconName(\"DatabaseMultiple\")\n                      .WithEnvironment(\"ACCEPT_EULA\", \"Y\")\n                      .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)","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.SqlServer/SqlServerBuilderExtensions.cs#L52-L88","documentation":"AddSqlServer hooks the ConnectionStringAvailableEvent to capture the resource's connection string. Aspire guarantees this event fires only once a connection string should exist, so if GetConnectionStringAsync still returns null the integration treats it as a broken invariant and throws DistributedApplicationException rather than silently continuing with a null connection string.","triggerScenarios":"The ConnectionStringAvailableEvent is published for the SqlServerServerResource but sqlServer.GetConnectionStringAsync(ct) returns null inside the OnConnectionStringAvailable callback — e.g. a customized/derived resource model overrides or clears the connection-string callback, the resource's ConnectionStringExpression/endpoint resolution yields nothing, or an extension replaced the resource's connection string provider.","commonSituations":"Custom resource builders or model transformations that strip the endpoint or connection-string annotation from the SQL Server resource; subclassing/reimplementing the resource with an incomplete ConnectionStringSetting; upstream Aspire eventing changes firing the event earlier than the value is computed.","solutions":["Inspect why GetConnectionStringAsync returned null: confirm the SQL Server resource still has its primary endpoint (WithEndpoint port/targetPort 1433) and connection-string contribution intact — do not remove or override it after AddSqlServer.","If you wrap or transform the resource (e.g. re-adding it under another resource type), re-apply the connection string/callback configuration that AddSqlServer registered.","Update the Aspire.Hosting.SqlServer integration package if a known regression between versions fires the event before the value is ready.","Reproduce with a minimal AppHost (only AddSqlServer) to rule out custom annotations/events as the cause."],"exampleFix":"// before (custom transformation drops the connection-string setup)\nvar sql = builder.AddSqlServer(\"sql\");\nbuilder.CreateResourceBuilder(sql.Resource); // new builder, events/annotations context disturbed\n\n// after\nvar sql = builder.AddSqlServer(\"sql\");\n// keep using the same builder instance so OnConnectionStringAvailable wiring stays intact\nvar sameBuilder = sql;","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try\n{\n    // start/await resource lifecycle\n}\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"ConnectionStringAvailableEvent was published\"))\n{\n    // connection-string provider is missing or broken; inspect resource annotations/endpoint config\n}","preventionTips":["Do not remove or override the primary endpoint or connection-string contribution of resources created by AddSqlServer.","Chain all customization on the IResourceBuilder returned by AddSqlServer instead of re-creating builders.","Keep Aspire.Hosting.SqlServer and Aspire.Hosting versions aligned to avoid eventing regressions.","Run a minimal AddSqlServer AppHost when debugging to isolate custom annotations as the cause."],"tags":["sqlserver","connection-string","eventing","invariant"],"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"}