apache/iceberg · error · IllegalArgumentException

Cannot initialize TLSConfigurer, %s does not implement TLSCo

Error message

Cannot initialize TLSConfigurer, %s does not implement TLSConfigurer.

What it means

HTTPClient instantiates the configured TLS implementation reflectively; if ctor.newInstance() returns an object that is not a TLSConfigurer, the ClassCastException is converted into an IllegalArgumentException with this message. The configured class exists and is constructible but does not implement the required interface.

Source

Thrown at core/src/main/java/org/apache/iceberg/rest/HTTPClient.java:462

    DynConstructors.Ctor<TLSConfigurer> ctor;
    try {
      ctor =
          DynConstructors.builder(TLSConfigurer.class)
              .loader(HTTPClient.class.getClassLoader())
              .impl(impl)
              .buildChecked();
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException(
          String.format(
              "Cannot initialize TLSConfigurer implementation %s: %s", impl, e.getMessage()),
          e);
    }

    TLSConfigurer configurer;
    try {
      configurer = ctor.newInstance();
    } catch (ClassCastException e) {
      throw new IllegalArgumentException(
          String.format(
              "Cannot initialize TLSConfigurer, %s does not implement TLSConfigurer.", impl),
          e);
    }

    configurer.initialize(properties);

    return configurer;
  }

  @VisibleForTesting
  static ConnectionConfig configureConnectionConfig(Map<String, String> properties) {
    Long connectionTimeoutMillis =
        PropertyUtil.propertyAsNullableLong(properties, REST_CONNECTION_TIMEOUT_MS);
    Integer socketTimeoutMillis =
        PropertyUtil.propertyAsNullableInt(properties, REST_SOCKET_TIMEOUT_MS);

    if (connectionTimeoutMillis == null && socketTimeoutMillis == null) {

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Make the configured class implement TLSConfigurer (and keep the public no-arg constructor).
  2. Set the config property to a genuine TLSConfigurer implementation class.
  3. Check the package of the interface your class implements — a similarly named interface from another library does not count.
  4. Upgrade/downgrade so client and implementation agree on the TLSConfigurer interface version.

Example fix

// before: wrong interface
class MyTls extends CustomSslFactory {}
// after
public class MyTls implements org.apache.iceberg.rest.auth.TLSConfigurer {
  public MyTls() {}
  public void initialize(Map<String, String> properties) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(implClassName);
if (!TLSConfigurer.class.isAssignableFrom(c)) {
  throw new IllegalArgumentException(implClassName + " does not implement TLSConfigurer");
}

Try / catch

try {
  buildClient();
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("does not implement TLSConfigurer")) {
    // correct the configured class or fall back to the default TLS configurer
  }
  throw e;
}

Prevention

When it happens

Trigger: Setting the TLS implementation config property to a class that exists and has a no-arg constructor but does not implement org.apache.iceberg.rest.auth.TLSConfigurer — e.g. a random SSLContext factory or a class from a different library.

Common situations: Copying config from another framework (e.g. pointing at a generic SSLSocketFactory class); refactoring renamed/moved the interface so the class no longer implements TLSConfigurer; wrong class picked from an autocomplete list.

Related errors


AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12). Data as JSON: /api/errors/84e8d8db4f864fbb. Report an issue: GitHub.