testcontainers/testcontainers-java · error · IllegalStateException

Elasticsearch must be configured either via constructor…

Error message

Elasticsearch must be configured either via constructor KibanaContainer(elasticsearch) or via .withElasticsearchUrl() for external Elasticsearch

What it means

Thrown during KibanaContainer.configure() when neither a managed ElasticsearchContainer was supplied via the constructor nor an external Elasticsearch URL was set via withElasticsearchUrl(). Kibana needs a target Elasticsearch cluster, so the container cannot be started without one of the two configuration paths.

Solutions

  1. Construct with a managed container: new KibanaContainer(new ElasticsearchContainer(...)) or elasticsearch container instance.
  2. For an external cluster, call kibana.withElasticsearchUrl("https://es.example.com:9200") before start().
  3. Verify your config-loading code actually sets one of the two options.

Example fix

// before
KibanaContainer kibana = new KibanaContainer();
kibana.start();
// after
KibanaContainer kibana = new KibanaContainer(elasticsearchContainer);
// or, for external ES:
KibanaContainer kibana = new KibanaContainer().withElasticsearchUrl("http://es:9200");
kibana.start();
Defensive patterns

Strategy: validation

Validate before calling

KibanaContainer kb = elasticsearch != null ? new KibanaContainer(elasticsearch)
    : esUrl != null ? new KibanaContainer().withElasticsearchUrl(esUrl)
    : throw new IllegalArgumentException("Provide an ElasticsearchContainer or an Elasticsearch URL");

Type guard

boolean isConfigured(KibanaContainer kb) { return kb != null && (managedEs != null || esUrl != null); }

Try / catch

try { kibana.start(); } catch (IllegalStateException e) { if (e.getMessage().contains("must be configured")) throw new ConfigException("Set KibanaContainer(elasticsearch) or withElasticsearchUrl()"); throw e; }

Prevention

When it happens

Trigger: Instantiating new KibanaContainer() with the no-arg constructor and starting it without calling withElasticsearchUrl(); or clearing/never setting both elasticsearch and elasticsearchUrl before start().

Common situations: Refactoring code that previously used the KibanaContainer(elasticsearch) constructor to the no-arg constructor and forgetting to add withElasticsearchUrl; building the container generically from config where both branches were skipped.

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 testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/9b322d2597ce30a7. Report an issue: GitHub.

Appendix: source

Thrown at modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/KibanaContainer.java:277

    }

    @Override
    protected void configure() {
        super.configure();

        addEnv("XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY", encryptionKey);
        addEnv("SERVER_NAME", "kibana");

        if (elasticsearchCaCertificate != null) {
            withCopyToContainer(Transferable.of(elasticsearchCaCertificate), ES_CA_CERT_PATH);
            addEnv("ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES", ES_CA_CERT_PATH);
        }
        if (elasticsearch != null) {
            configureManagedElasticsearch();
        } else if (elasticsearchUrl != null) {
            configureExternalElasticsearch();
        } else {
            throw new IllegalStateException(
                "Elasticsearch must be configured either via constructor KibanaContainer(elasticsearch) " +
                "or via .withElasticsearchUrl() for external Elasticsearch"
            );
        }
        //wait strategy is set in configure, because we don't know the security configuration before
        configureWaitStrategy();
    }

    @Override
    protected void containerIsStarted(InspectContainerResponse containerInfo) {
        super.containerIsStarted(containerInfo);
        log.info("Kibana is now ready, it can be accessed at http://{}", getHttpHostAddress());
    }

    @Override
    public void stop() {
        super.stop();
        if (createdSharedNetwork != null) {

View on GitHub (pinned to 8e549514e3)