apache/iceberg · error · java.lang.RuntimeException
Failed to instantiate DynamicRecordGeneratorSQL %s
Error message
Failed to instantiate DynamicRecordGeneratorSQL %s
What it means
After the interface check, IcebergTableSink instantiates the configured DynamicRecordGeneratorSQL reflectively via a compatible constructor; any failure (no matching ctor, reflective invocation exception, classloading errors) is wrapped in this RuntimeException naming the class.
Source
Thrown at flink/v2.1/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
- Add public constructors matching (RowType) and (RowType, Map<String,String>, Configuration) to the generator class
- Inspect the cause chain of the RuntimeException to find the real construction failure and fix it (config value, dependency)
- Ensure the generator jar is on the Flink job classpath and built against the same Iceberg/Flink versions
Example fix
// before
class MyGen implements DynamicRecordGeneratorSQL { MyGen(){} } // no matching ctor
// after
class MyGen implements DynamicRecordGeneratorSQL {
public MyGen(RowType rowType) {...}
public MyGen(RowType rowType, Map<String,String> props, Configuration conf) {...}
} Defensive patterns
Strategy: try-catch
Validate before calling
for (Constructor<?> ctor : Class.forName(generatorImpl).getConstructors()) {
// require (RowType) or (RowType, Map, Configuration)
} Try / catch
try {
generator = sink.createDynamicRecordGenerator(rowType);
} catch (RuntimeException e) {
LOG.error("Failed to instantiate generator {} — check constructor signature and cause", generatorImpl, e.getCause());
throw e;
} Prevention
- Implement both required constructors in every generator
- Build the generator against the same Iceberg/Flink versions as the job
- Fail fast in the constructor with clear messages on bad config
- Ensure the generator jar ships in the Flink job (shade or lib dir)
When it happens
Trigger: Configured generator class implements the interface but lacks a (RowType) or (RowType, Map, Configuration) constructor, its constructor throws, or the class cannot be loaded from the sink's classloader.
Common situations: Generator written for a different Iceberg version's constructor signature; constructor throwing during initialization (bad config parsing); shaded/missing dependencies inside the generator class.
Related errors
- Failed to instantiate DynamicRecordGeneratorSQL %s
- Failed to instantiate DynamicRecordGeneratorSQL %s
- Failed to instantiate DynamicRecordGeneratorSQL %s
- org.apache.iceberg.arrow.vectorized.ArrowVectorAccessors can
- Cannot initialize AdlsTokenCredentialProvider, missing no-ar
AI-assisted analysis of apache/iceberg@86d9c8fc54 (2026-09-12).
Data as JSON: /api/errors/44ae6b101a9db4b5.
Report an issue: GitHub.