microsoft/aspire · error · InvalidOperationException

Connection string is unavailable

Error message

Connection string is unavailable

What it means

The Kafka health check factory builds a Kafka ProducerConfig from the resource's resolved connection string. If the connection string is null at the time the health check is registered, Aspire throws this InvalidOperationException because a Kafka health check cannot probe a broker without bootstrap servers. It guards against registering a health check with unusable configuration.

Solutions

  1. Ensure the Kafka resource has a valid connection string (e.g. it was created via AddKafka and has endpoints registered) before calling AddKafka's health check registration path.
  2. If you pass an explicit connection string, verify it is not null/empty at the call site.
  3. Run the app model after resource building completes so GetValueAsync of the connection string has a resolved value.
  4. If using a custom resource wrapper, implement IResourceWithConnectionString correctly so the connection-string callback returns a non-null expression.

Example fix

// before
builder.AddKafka("kafka", connectionString: null);

// after
var kafka = builder.AddKafka("kafka");
kafka.WithHealthCheck(); // connection string resolved from the resource model
Defensive patterns

Strategy: validation

Validate before calling

var cs = resource.GetConnectionStringAsync(cts.Token).Result; // or await
if (string.IsNullOrEmpty(cs)) throw new InvalidOperationException("Kafka resource has no connection string before health check registration");

Prevention

When it happens

Trigger: Calling AddKafka on a builder whose Kafka resource has no connection string available at registration time — e.g. a resource added without WithReference or without a completed connection-string callback, or passing connectionString: null explicitly.

Common situations: Developers call AddKafka on a Kafka server resource before its connection string has been computed (runs before the resource is fully configured), or re-use a connection-string retrieval that returns null when the resource has no endpoint bindings yet.

Understand the failure class

Background: "X is required", "must be set", "cannot be empty": the missing-required-config error family, from Vertex AI project/location to WeChat keys — this error's family across 18 libraries.

Related errors


AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/464dd79ae1b243e9. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Hosting.Kafka/KafkaBuilderExtensions.cs:62

        {
            connectionString = await kafka.ConnectionStringExpression.GetValueAsync(ct).ConfigureAwait(false);

            if (connectionString == null)
            {
                throw new DistributedApplicationException($"ConnectionStringAvailableEvent was published for the '{kafka.Name}' resource but the connection string was null.");
            }
        });

        var healthCheckKey = $"{name}_check";

        // DI must own the check so its producer is reused and disposed with the AppHost.
        // Key it per resource to avoid sharing the last resource's connection string:
        // https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks/issues/2298
        builder.Services.AddKeyedSingleton<KafkaHealthCheck>(healthCheckKey, (sp, _) =>
        {
            var options = new KafkaHealthCheckOptions();
            options.Configuration = new ProducerConfig();
            options.Configuration.BootstrapServers = connectionString ?? throw new InvalidOperationException("Connection string is unavailable");
            return new KafkaHealthCheck(options);
        });

        var healthCheckRegistration = new HealthCheckRegistration(
            healthCheckKey,
            sp => sp.GetRequiredKeyedService<KafkaHealthCheck>(healthCheckKey),
            failureStatus: default,
            tags: default);
        builder.Services.AddHealthChecks().Add(healthCheckRegistration);

        return builder.AddResource(kafka)
            .WithEndpoint(targetPort: KafkaBrokerPort, port: port, name: KafkaServerResource.PrimaryEndpointName)
            .WithEndpoint(targetPort: KafkaInternalBrokerPort, name: KafkaServerResource.InternalEndpointName)
            .WithImage(KafkaContainerImageTags.Image, KafkaContainerImageTags.Tag)
            .WithImageRegistry(KafkaContainerImageTags.Registry)
            .WithIconName("MailMultiple")
            .WithEnvironment(context => ConfigureKafkaContainer(context, kafka))
            .WithHealthCheck(healthCheckKey);

View on GitHub (pinned to 25830f84bd)