{"record":{"id":"ab4a65046fc1e757","repo":"microsoft/aspire","slug":"connectionstringavailableevent-was-published-for-the-valkey","errorCode":null,"errorMessage":"ConnectionStringAvailableEvent was published for the '{valkey.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.Valkey/ValkeyBuilderExtensions.cs","lineNumber":136,"sourceCode":"        ArgumentNullException.ThrowIfNull(builder);\n        ArgumentException.ThrowIfNullOrEmpty(name);\n\n        // StackExchange.Redis doesn't support passwords with commas.\n        // See https://github.com/StackExchange/StackExchange.Redis/issues/680 and\n        // https://github.com/Azure/azure-dev/issues/4848 \n        var passwordParameter = password?.Resource ?? ParameterResourceBuilderExtensions.CreateDefaultPasswordParameter(builder, $\"{name}-password\", special: false);\n\n        var valkey = new ValkeyResource(name, passwordParameter);\n\n        string? connectionString = null;\n\n        builder.Eventing.Subscribe<ConnectionStringAvailableEvent>(valkey, async (@event, ct) =>\n        {\n            connectionString = await valkey.ConnectionStringExpression.GetValueAsync(ct).ConfigureAwait(false);\n\n            if (connectionString is null)\n            {\n                throw new DistributedApplicationException($\"ConnectionStringAvailableEvent was published for the '{valkey.Name}' resource but the connection string was null.\");\n            }\n        });\n\n        var healthCheckKey = $\"{name}_check\";\n        builder.Services.AddHealthChecks()\n            .AddRedis(sp => connectionString ?? throw new InvalidOperationException(\"Connection string is unavailable\"), name: healthCheckKey);\n\n        return builder.AddResource(valkey)\n            .WithEndpoint(port: port, targetPort: 6379, name: ValkeyResource.PrimaryEndpointName)\n            .WithImage(ValkeyContainerImageTags.Image, ValkeyContainerImageTags.Tag)\n            .WithImageRegistry(ValkeyContainerImageTags.Registry)\n            .WithIconName(\"Database\")\n            .WithHealthCheck(healthCheckKey)\n            // see https://github.com/microsoft/aspire/issues/3838 for why the password is passed this way\n            .WithEntrypoint(\"/bin/sh\")\n            .WithEnvironment(context =>\n            {\n                if (valkey.PasswordParameter is { } password)","sourceCodeStart":118,"sourceCodeEnd":154,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Valkey/ValkeyBuilderExtensions.cs#L118-L154","documentation":"When a Valkey resource's connection string becomes available, Aspire publishes ConnectionStringAvailableEvent and the handler resolves the resource's ConnectionStringExpression. If the resolved value is null, AddValkey throws this DistributedApplicationException because downstream code (health checks, client integrations) cannot function without a connection string.","triggerScenarios":"Subscribing to ConnectionStringAvailableEvent for a ValkeyResource whose ConnectionStringExpression evaluates to null — typically when the resource has no primary endpoint/reference configured or the expression resolves before the endpoint exists.","commonSituations":"Misconfigured ValkeyResource (endpoint removed or overridden), custom resource subclassing Valkey without a connection-string expression, running the resource in an unusual mode (e.g. published without endpoints), or event published prematurely in custom eventing code.","solutions":["Ensure the Valkey resource has its primary endpoint (don't remove/override WithEndpoint for the 6379 endpoint).","Check that no custom code clears or replaces the resource's ConnectionStringExpression.","If subclassing, verify the constructor passes a non-null connection-string expression (e.g. built from the primary endpoint reference).","Reproduce with minimal AddValkey('valkey') call to rule out custom configuration as the cause."],"exampleFix":"// before\nvar valkey = builder.AddValkey(\"cache\");\nvalkey.Resource.Endpoints.Clear(); // breaks connection string resolution\n// after\nvar valkey = builder.AddValkey(\"cache\"); // keep default endpoint intact","handlingStrategy":"validation","validationCode":"if (valkey.Resource.ConnectionStringExpression is null)\n    throw new InvalidOperationException(\"Valkey resource has no connection string expression\");","typeGuard":null,"tryCatchPattern":"try { var app = await builder.BuildAsync(); await app.StartAsync(); }\ncatch (DistributedApplicationException ex) when (ex.Message.Contains(\"connection string was null\"))\n{\n    // log resource misconfiguration and abort startup\n}","preventionTips":["Keep default endpoints on Valkey resources.","Don't mutate resource endpoints after creation.","Review custom resource subclasses for null connection-string expressions."],"tags":["valkey","connection-string","aspire"],"backgroundTag":"missing-config-value","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"}