apache/beam · error · IllegalArgumentException

Config class must be not null!

Error message

Config class must be not null!

What it means

PluginConfigInstantiationUtils.getPluginConfig validates that the PluginConfig subclass passed for reflective instantiation is non-null before walking its field hierarchy. A null configClass would make reflection impossible, so an IllegalArgumentException is thrown immediately.

Source

Thrown at sdks/java/io/cdap/src/main/java/org/apache/beam/sdk/io/cdap/PluginConfigInstantiationUtils.java:56

public class PluginConfigInstantiationUtils {

  private static final Logger LOG = LoggerFactory.getLogger(PluginConfigInstantiationUtils.class);
  private static final String MACRO_FIELDS_FIELD_NAME = "macroFields";

  /**
   * Method for instantiating {@link PluginConfig} object of specific class {@code configClass}.
   * After instantiating, it will go over all {@link Field}s with the {@link Name} annotation and
   * set the appropriate parameter values from the {@code params} map for them.
   *
   * @param params map of config fields, where key is the name of the field, value must be String or
   *     boxed primitive
   * @return Config object for given map of arguments and configuration class
   */
  static @Nullable <T extends PluginConfig> T getPluginConfig(
      Map<String, Object> params, Class<T> configClass) {
    // Validate configClass
    if (configClass == null) {
      throw new IllegalArgumentException("Config class must be not null!");
    }
    List<Field> allFields = new ArrayList<>();
    Class<?> currClass = configClass;
    while (currClass != null && !currClass.equals(Object.class)) {
      allFields.addAll(
          Arrays.stream(currClass.getDeclaredFields())
              .filter(f -> !Modifier.isStatic(f.getModifiers()))
              .collect(Collectors.toList()));
      currClass = currClass.getSuperclass();
    }
    InstantiatorFactory instantiatorFactory = new InstantiatorFactory(false);

    @Initialized T config = instantiatorFactory.get(TypeToken.of(configClass)).create();

    if (config != null) {
      for (Field field : allFields) {
        field.setAccessible(true);

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass the concrete PluginConfig subclass (e.g., MyPluginConfig.class) instead of null
  2. If the config class comes from generics, capture it explicitly via a TypeToken or pass the Class literal at the call site
  3. Check the builder/factory that supplies configClass for a code path that leaves it unset

Example fix

// before
PluginConfig config = PluginConfigInstantiationUtils.getPluginConfig(params, null);
// after
PluginConfig config = PluginConfigInstantiationUtils.getPluginConfig(params, MyPluginConfig.class);
Defensive patterns

Strategy: type-guard

Validate before calling

if (configClass == null) {
  throw new IllegalArgumentException("configClass must be provided to getPluginConfig");
}

Type guard

static <T extends PluginConfig> boolean validConfigClass(Class<T> c) {
  return c != null && PluginConfig.class.isAssignableFrom(c);
}

Try / catch

try {
  return PluginConfigInstantiationUtils.getPluginConfig(params, configClass);
} catch (IllegalArgumentException e) {
  if (e.getMessage().contains("Config class must be not null")) { /* resolve config class from generics */ }
  throw e;
}

Prevention

When it happens

Trigger: Calling getPluginConfig(params, null) — typically from a CDAP IO wrapper whose config class was resolved to null, e.g., a generic type parameter that could not be resolved, or a Plugin.of(...) call where the config class argument was null.

Common situations: Passing null because a generic config type was erased or not captured; accidentally passing the plugin class's config field value (null at that point) instead of the class itself; miswiring a builder where the config class is set later than first use.

Related errors


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/ac6ccdb4dbc12832. Report an issue: GitHub.