apache/beam · error · IllegalStateException

Can not call prepareRun

Error message

Can not call prepareRun

What it means

Plugin.instantiateCdapPluginObj() reflectively instantiates the plugin class via its constructor taking the plugin config type. Any failure (missing constructor, wrong config type, instantiation error) is rethrown as IllegalStateException('Can not call prepareRun'), obscuring the reflective failure.

Solutions

  1. Check the wrapped cause in logs (LOG.error prints the real exception).
  2. Ensure the plugin class declares a constructor matching the exact pluginConfig type used by the connector.
  3. Align plugin/config versions (rebuild the plugin against the connector's expected API).
  4. Verify the plugin class is present on the pipeline classpath at runtime.

Example fix

// before: plugin lacks matching constructor
public class MySink extends BatchSink<...> { public MySink(SinkConfig cfg) {...} }
// after: add constructor for the exact config class used by the connector
public class MySink extends BatchSink<...> {
  public MySink(com.google.cloud.verticals.foundations.dataharmonization.plugins.MySinkConfig cfg) {...}
}
Defensive patterns

Strategy: try-catch

Validate before calling

try {
  pluginClass.getConstructor(pluginConfig.getClass());
} catch (NoSuchMethodException e) {
  throw new IllegalArgumentException(pluginClass.getName() + " lacks constructor for " + pluginConfig.getClass());
}

Try / catch

try { pipeline.run().waitUntilFinish(); } catch (IllegalStateException e) {
  if ("Can not call prepareRun".equals(e.getMessage())) {
    e.printStackTrace(); // check LOG output for the true reflective cause
  }
  throw e;
}

Prevention

When it happens

Trigger: CdapIO/Plugin.prepareRun() when getPluginClass() has no declared constructor accepting the pluginConfig's class, or instantiation throws (bad config contents, class loading issue).

Common situations: Plugin class/config version mismatch (config class differs from plugin's expected constructor type); plugin class not on classpath; pluginConfig is of an unexpected subtype.

Related errors


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

Appendix: source

Thrown at sdks/java/io/cdap/src/main/java/org/apache/beam/sdk/io/cdap/Plugin.java:147

      for (Map.Entry<String, String> entry :
          getContext().getOutputFormatProvider().getOutputFormatConfiguration().entrySet()) {
        getHadoopConfiguration().set(entry.getKey(), entry.getValue());
      }
      getHadoopConfiguration().set(MRJobConfig.ID, String.valueOf(1));
    }
  }

  /** Creates an instance of {@link #cdapPluginObj} using {@link #pluginConfig}. */
  private void instantiateCdapPluginObj() {
    PluginConfig pluginConfig = getPluginConfig();
    checkStateNotNull(pluginConfig, "PluginConfig should be not null!");
    try {
      Constructor<?> constructor = getPluginClass().getDeclaredConstructor(pluginConfig.getClass());
      constructor.setAccessible(true);
      cdapPluginObj = (SubmitterLifecycle) constructor.newInstance(pluginConfig);
    } catch (Exception e) {
      LOG.error("Can not instantiate CDAP plugin class", e);
      throw new IllegalStateException("Can not call prepareRun");
    }
  }

  /** Sets a plugin Hadoop configuration. */
  public Plugin<K, V> withHadoopConfiguration(Class<K> formatKeyClass, Class<V> formatValueClass) {
    Class<?> formatClass = getFormatClass();
    checkStateNotNull(formatClass, "Format class can't be null!");
    PluginConstants.Format formatType = getFormatType();
    PluginConstants.Hadoop hadoopType = getHadoopType();

    getHadoopConfiguration()
        .setClass(hadoopType.getFormatClass(), formatClass, formatType.getFormatClass());
    getHadoopConfiguration().setClass(hadoopType.getKeyClass(), formatKeyClass, Object.class);
    getHadoopConfiguration().setClass(hadoopType.getValueClass(), formatValueClass, Object.class);

    return this;
  }

View on GitHub (pinned to 12126d8942)