{"record":{"id":"21e6154d06df4963","repo":"microsoft/aspire","slug":"connectionstringavailableevent-was-published-for-the-21e615","errorCode":null,"errorMessage":"ConnectionStringAvailableEvent was published for the '{postgresServer.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":"critical","filePath":"src/Aspire.Hosting.PostgreSQL/PostgresBuilderExtensions.cs","lineNumber":69,"sourceCode":"        IResourceBuilder<ParameterResource>? password = null,\n        int? port = null)\n    {\n        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrEmpty(name);\n\n        var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $\"{name}-password\");\n\n        var postgresServer = new PostgresServerResource(name, userName?.Resource, passwordParameter);\n\n        string? connectionString = null;\n\n        builder.Eventing.Subscribe<ConnectionStringAvailableEvent>(postgresServer, async (@event, ct) =>\n        {\n            connectionString = await postgresServer.GetConnectionStringAsync(ct).ConfigureAwait(false);\n\n            if (connectionString == null)\n            {\n                throw new DistributedApplicationException($\"ConnectionStringAvailableEvent was published for the '{postgresServer.Name}' resource but the connection string was null.\");\n            }\n        });\n\n        builder.Eventing.Subscribe<ResourceReadyEvent>(postgresServer, async (@event, ct) =>\n        {\n            if (connectionString is null)\n            {\n                throw new DistributedApplicationException($\"ResourceReadyEvent was published for the '{postgresServer.Name}' resource but the connection string was null.\");\n            }\n\n            // Non-database scoped connection string\n            using var npgsqlConnection = new NpgsqlConnection(connectionString + \";Database=postgres;\");\n\n            await npgsqlConnection.OpenAsync(ct).ConfigureAwait(false);\n\n            if (npgsqlConnection.State != System.Data.ConnectionState.Open)\n            {\n                throw new InvalidOperationException($\"Could not open connection to '{postgresServer.Name}'\");","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.PostgreSQL/PostgresBuilderExtensions.cs#L51-L87","documentation":"AddPostgres subscribes to ConnectionStringAvailableEvent for the PostgresServerResource and caches the value of GetConnectionStringAsync. If the event fires but the connection string is null, the resource model is inconsistent (the event guarantees a value), so a DistributedApplicationException is thrown. The cached string is later used for database creation and health checks.","triggerScenarios":"ConnectionStringAvailableEvent published for postgresServer while GetConnectionStringAsync returns null — e.g. a missing/invalid parameter or endpoint backing the connection string expression.","commonSituations":"Custom Postgres resource overrides that produce a null expression result; running the AppHost without required configuration; premature manual event publication.","solutions":["Ensure the Postgres server resource has its username/password parameters and endpoint configured (defaults from AddPostgres).","If overriding the connection string expression, guarantee a non-null result or fail earlier with a clearer error.","Avoid publishing ConnectionStringAvailableEvent manually before the resource model is complete."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Ensure username/password parameters exist so the connection string resolves\nif (builder.Configuration[\"Parameters:postgres-username\"] is null ||\n    builder.Configuration[\"Parameters:postgres-password\"] is null)\n{\n    // defaults exist, but custom overrides must supply values\n    logger.LogWarning(\"Postgres parameters missing; connection string may not resolve.\");\n}","typeGuard":null,"tryCatchPattern":"try { var cs = await postgresServer.GetConnectionStringAsync(ct); } catch (DistributedApplicationException ex) { logger.LogError(ex, \"Postgres connection string invariant broken\"); throw; }","preventionTips":["Use default AddPostgres wiring (parameters + endpoint)","Never publish ConnectionStringAvailableEvent manually","Keep required parameters configured for every environment"],"tags":["aspire","postgresql","connection-string","eventing"],"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-21T09:17:21.228Z"}