elastic/elasticsearch · error · IllegalArgumentException

telemetry.logs.ssl.certificate and telemetry.logs.ssl.key mu

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.

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)

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.