apache/iceberg · error · RuntimeException

Failed to instantiate DynamicRecordGeneratorSQL %s

Error message

Failed to instantiate DynamicRecordGeneratorSQL %s

What it means

createDynamicRecordGenerator wraps any instantiation failure (constructor lookup error, invocation failure, wrong constructor signature) in a RuntimeException naming the generator class. It means reflection could not construct an instance of the configured DynamicRecordGeneratorSQL implementation for the given RowType, write properties, and configuration.

Source

Thrown at flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/IcebergTableSink.java:296

  private DynamicTableRecordGenerator createDynamicRecordGenerator(String generatorImpl) {
    RowType rowType = (RowType) resolvedSchema.toSourceRowDataType().getLogicalType();

    DynConstructors.Ctor<DynamicTableRecordGenerator> ctor;

    try {
      ctor =
          DynConstructors.builder(DynamicTableRecordGenerator.class)
              .loader(IcebergTableSink.class.getClassLoader())
              .impl(generatorImpl, RowType.class)
              .impl(generatorImpl, RowType.class, Map.class, Configuration.class)
              .buildChecked();
      return ctor.newInstance(rowType, writeProps, fromReadableConfig());
    } catch (ClassCastException e) {
      throw new IllegalArgumentException(
          String.format("Class %s does not implement DynamicRecordGeneratorSQL", generatorImpl), e);
    } catch (Exception e) {
      throw new RuntimeException(
          String.format("Failed to instantiate DynamicRecordGeneratorSQL %s", generatorImpl), e);
    }
  }

  private Configuration fromReadableConfig() {
    return readableConfig instanceof Configuration
        ? (Configuration) readableConfig
        : Configuration.fromMap(readableConfig.toMap());
  }
}

View on GitHub (pinned to 86d9c8fc54)

Solutions

  1. Ensure the generator exposes a public constructor accepting (RowType, Map<String,String>, Configuration) or (RowType, Map<String,String>).
  2. Make the class public with a public constructor; check the cause stack trace for the underlying error.
  3. Rebuild the generator against the exact Iceberg Flink version in use.

Example fix

// before
class MyGen implements DynamicRecordGeneratorSQL { MyGen(RowType t) {...} } // no matching ctor
// after
public class MyGen implements DynamicRecordGeneratorSQL {
  public MyGen(RowType rowType, Map<String, String> props, Configuration conf) { ... }
}
Defensive patterns

Strategy: validation

Validate before calling

Class<?> c = Class.forName(generatorImpl);
boolean hasCtor = Arrays.stream(c.getConstructors()).anyMatch(k ->
    k.getParameterCount() == 3 && k.getParameterTypes()[0] == RowType.class);
if (!hasCtor) throw new IllegalStateException("Generator lacks (RowType, Map, Configuration) ctor");

Try / catch

try { sink.write(...); } catch (RuntimeException e) { LOG.error("generator instantiation failed", e.getCause()); }

Prevention

When it happens

Trigger: Configured generator class has no constructor matching (RowType), (RowType, Map), or (RowType, Map, Configuration); constructor throws; class lacks a public no-arg-accessible ctor; Class.forName fails during the Dissatisfied loader build.

Common situations: Custom generator built against a different Iceberg version so constructor signatures changed; class not public; constructor throwing on bad write properties.

Related errors


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