{"record":{"id":"f7f702e73e1b3a7f","repo":"apache/iceberg","slug":"failed-to-instantiate-dynamicrecordgeneratorsql-s","errorCode":null,"errorMessage":"Failed to instantiate DynamicRecordGeneratorSQL %s","messagePattern":"Failed to instantiate DynamicRecordGeneratorSQL (.+?)","errorType":"exception","errorClass":"java.lang.RuntimeException","httpStatus":null,"severity":"error","filePath":"flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/IcebergTableSink.java","lineNumber":298,"sourceCode":"  }\n\n  private DynamicTableRecordGenerator createDynamicRecordGenerator(String generatorImpl) {\n    RowType rowType = (RowType) resolvedSchema.toSourceRowDataType().getLogicalType();\n\n    DynConstructors.Ctor<DynamicTableRecordGenerator> ctor;\n\n    try {\n      ctor =\n          DynConstructors.builder(DynamicTableRecordGenerator.class)\n              .loader(IcebergTableSink.class.getClassLoader())\n              .impl(generatorImpl, RowType.class)\n              .buildChecked();\n      return ctor.newInstance(rowType);\n    } catch (ClassCastException e) {\n      throw new IllegalArgumentException(\n          String.format(\"Class %s does not implement DynamicRecordGeneratorSQL\", generatorImpl), e);\n    } catch (Exception e) {\n      throw new RuntimeException(\n          String.format(\"Failed to instantiate DynamicRecordGeneratorSQL %s\", generatorImpl), e);\n    }\n  }\n}\n","sourceCodeStart":280,"sourceCodeEnd":303,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v1.20/flink/src/main/java/org/apache/iceberg/flink/IcebergTableSink.java#L280-L303","documentation":"IcebergTableSink.createDynamicRecordGenerator wraps any failure other than the interface-mismatch ClassCastException (e.g. ClassNotFoundException, missing (RowType) constructor, or constructor exceptions) into a RuntimeException naming the configured generator class. It means the configured DynamicTableRecordGenerator implementation could not be found or constructed reflectively.","triggerScenarios":"Configuring the sink's dynamic record generator option to a class that is not on the classpath, has no public constructor accepting a single RowType argument, or throws from its constructor, when the Iceberg sink initializes the generator.","commonSituations":"Missing or misspelled class name in sink options; generator jar not distributed to all TaskManagers; constructor signature changed after an upgrade; generator constructor throwing due to bad config; shaded fat jar excluding the generator class.","solutions":["Add a public constructor taking exactly one RowType parameter: public MyGen(RowType rowType) { ... }.","Ensure the jar containing the generator is on the Flink classpath (flink/lib or bundled in the user job jar) and the class name in the option is correct.","Inspect the wrapped cause: ClassNotFoundException means classpath, NoSuchMethodException means constructor signature, other exceptions mean the constructor body threw.","Recompile the generator against your exact iceberg-flink version; API changes can break the expected constructor or interface.","Remove the custom generator option to use the default generator."],"exampleFix":"// before\npublic MyGen() { } // no RowType constructor\n// after\npublic MyGen(RowType rowType) {\n  this.rowType = rowType;\n}\n// plus: flink run -C my-jar-with-generator.jar ...","handlingStrategy":"validation","validationCode":"// Verify the class is loadable and has the required (RowType) constructor before configuring\nClass<?> cls;\ntry {\n  cls = Class.forName(\"com.example.MyGen\", false,\n      Thread.currentThread().getContextClassLoader());\n} catch (ClassNotFoundException e) {\n  throw new IllegalStateException(\"Generator class not on classpath: com.example.MyGen\", e);\n}\ntry {\n  cls.getConstructor(org.apache.flink.table.types.logical.RowType.class);\n} catch (NoSuchMethodException e) {\n  throw new IllegalStateException(\"Generator needs a public MyGen(RowType) constructor\", e);\n}","typeGuard":null,"tryCatchPattern":"try {\n  sink = ...; // sink creation that instantiates the generator\n} catch (RuntimeException e) {\n  if (e.getMessage() != null && e.getMessage().startsWith(\"Failed to instantiate DynamicRecordGeneratorSQL\")) {\n    Throwable cause = e.getCause();\n    LOG.error(\"Generator init failed ({}): check classpath and RowType constructor\",\n        cause == null ? \"unknown\" : cause.getClass().getSimpleName(), e);\n  }\n  throw e;\n}","preventionTips":["Ship the generator class in the user job jar so it reaches every TaskManager.","Provide a public constructor accepting exactly one RowType argument.","Keep constructor logic side-effect-free; validate config lazily to avoid instantiation throws.","Log the wrapped cause when debugging: ClassNotFoundException = classpath, NoSuchMethodException = signature, other = constructor body threw."],"tags":["flink","iceberg","reflection","configuration","instantiation"],"backgroundTag":"class-not-found","analyzedSha":"86d9c8fc543e7c56c9f624eb725f76c9baff9570","analyzedAt":"2026-09-12T00:46:39.097Z","contentChangedAt":"2026-09-12T00:46:39.097Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}