apache/iceberg · error · IllegalArgumentException

Cannot initialize AwsClientFactory, missing no-arg construct

Error message

Cannot initialize AwsClientFactory, missing no-arg constructor: %s

What it means

AwsClientFactories.from(properties) loads a custom AwsClientFactory implementation class named by the warehouse/client property 'client.factory-impl' via reflection (DynConstructors, hidden constructors allowed). This error is thrown when the class was found but has no accessible no-argument constructor, so it cannot be instantiated before factory.initialize(properties) is called. The IllegalArgumentException wraps the underlying NoSuchMethodException.

Source

Thrown at aws/src/main/java/org/apache/iceberg/aws/AwsClientFactories.java:75

  }

  public static AwsClientFactory from(Map<String, String> properties) {
    String factoryImpl =
        PropertyUtil.propertyAsString(
            properties, AwsProperties.CLIENT_FACTORY, DefaultAwsClientFactory.class.getName());
    return loadClientFactory(factoryImpl, properties);
  }

  private static AwsClientFactory loadClientFactory(String impl, Map<String, String> properties) {
    DynConstructors.Ctor<AwsClientFactory> ctor;
    try {
      ctor =
          DynConstructors.builder(AwsClientFactory.class)
              .loader(AwsClientFactories.class.getClassLoader())
              .hiddenImpl(impl)
              .buildChecked();
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException(
          String.format("Cannot initialize AwsClientFactory, missing no-arg constructor: %s", impl),
          e);
    }

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

    factory.initialize(properties);
    return factory;
  }

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Add a public no-argument constructor to the implementation class and receive configuration via factory.initialize(Map<String, String>).
  2. Verify the property value points at the intended fully-qualified class name.
  3. If the factory cannot be made no-arg, use a different customization mechanism (e.g. configure the built-in factories via catalog properties).

Example fix

// before
public class MyFactory implements AwsClientFactory {
  public MyFactory(String region) { ... }
}
// after
public class MyFactory implements AwsClientFactory {
  public MyFactory() {}
  @Override
  public void initialize(Map<String, String> properties) { this.region = properties.get("region"); }
}
Defensive patterns

Strategy: validation

Validate before calling

String impl = props.get("client.factory-impl");
Class<?> c = Class.forName(impl);
if (Arrays.stream(c.getConstructors()).noneMatch(ctor -> ctor.getParameterCount() == 0)) {
  throw new IllegalStateException(impl + " must expose a public no-arg constructor");
}

Try / catch

try {
  factory = AwsClientFactories.from(props);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("missing no-arg constructor")) {
    throw new IllegalStateException("Fix client.factory-impl: class needs a public no-arg constructor and config via initialize()", e);
  }
  throw e;
}

Prevention

When it happens

Trigger: Setting client.factory-impl (or the catalog's client.factory property) to a class that only has parameterized constructors, e.g. a factory requiring constructor arguments, or a class with an explicit constructor taking config so no implicit no-arg constructor exists.

Common situations: Users copying a factory class from an example but keeping a constructor that takes arguments; Kotlin/Scala objects or classes with required constructor params; class compiled with a constructor signature that changed between versions.

Related errors


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