elastic/elasticsearch · error · IllegalArgumentException

telemetry.logs.ssl.certificate and telemetry.logs.ssl.key…

Error message

telemetry.logs.ssl.certificate and telemetry.logs.ssl.key must both be set or both be unset

What it means

telemetry.logs.ssl.certificate is a simpleString with a paired validator: it checks that telemetry.logs.ssl.key is in the same emptiness state. If exactly one of {certificate, key} is set (cert present + key absent, or vice-versa) the validator throws IllegalArgumentException. This is the cert-side of the pair; an identical check is performed from the key setting.

Solutions

  1. Provide both telemetry.logs.ssl.certificate and telemetry.logs.ssl.key, OR omit both (to disable mTLS client auth).
  2. When rotating, update both keys atomically in a single cluster update-settings call.
  3. Verify paths point to readable PEM files for both.

Example fix

// before
telemetry.logs.ssl.certificate: certs/client.crt
// missing key
// after
telemetry.logs.ssl.certificate: certs/client.crt
telemetry.logs.ssl.key: certs/client.key
Defensive patterns

Strategy: validation

Validate before calling

// cert and key must be both-set or both-unset
static String check(String cert, String key) {
  if (cert.isEmpty() != key.isEmpty())
    return "telemetry.logs.ssl.certificate and telemetry.logs.ssl.key must both be set or both be unset";
  return null;
}

Prevention

When it happens

Trigger: Configuring telemetry.logs.ssl.certificate without telemetry.logs.ssl.key, or vice-versa, in elasticsearch.yml or via cluster update settings.

Common situations: Uploading only the public cert during mTLS setup; rotating one half of the pair; copy-paste that dropped the key line.

Understand the failure class

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/14858e434db15251. Report an issue: GitHub.

Appendix: source

Thrown at modules/apm/src/main/java/org/elasticsearch/telemetry/apm/internal/export/otelsdk/OtelSdkSettings.java:300

    );

    /**
     * Path to the PEM-encoded client certificate for mTLS authentication to the otel-delivery-gateway.
     * Must be set together with {@link #TELEMETRY_LOGS_SSL_KEY}.
     * Path is resolved relative to the Elasticsearch config directory when not absolute.
     */
    public static final Setting<String> TELEMETRY_LOGS_SSL_CERTIFICATE = Setting.simpleString(
        "telemetry.logs.ssl.certificate",
        "",
        new Setting.Validator<>() {
            @Override
            public void validate(String value) {}

            @Override
            public void validate(String value, Map<Setting<?>, Object> settings) {
                String key = (String) settings.get(TELEMETRY_LOGS_SSL_KEY);
                if (value.isEmpty() != key.isEmpty()) {
                    throw new IllegalArgumentException(
                        TELEMETRY_LOGS_SSL_CERTIFICATE.getKey()
                            + " and "
                            + TELEMETRY_LOGS_SSL_KEY.getKey()
                            + " must both be set or both be unset"
                    );
                }
            }

            @Override
            public Iterator<Setting<?>> settings() {
                return List.<Setting<?>>of(TELEMETRY_LOGS_SSL_KEY).iterator();
            }
        },
        NodeScope
    );

    /**
     * Path to the PEM-encoded private key for the client certificate ({@link #TELEMETRY_LOGS_SSL_CERTIFICATE}).

View on GitHub (pinned to db6a809a66)