{"record":{"id":"37e8466bbf1cca5c","repo":"apache/iceberg","slug":"class-s-does-not-implement-dynamicrecordgenerator-37e846","errorCode":null,"errorMessage":"Class %s does not implement DynamicRecordGeneratorSQL","messagePattern":"Class (.+?) does not implement DynamicRecordGeneratorSQL","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/IcebergTableSink.java","lineNumber":293,"sourceCode":"            .withProperties(tableProperties)\n            .create();\n  }\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              .impl(generatorImpl, RowType.class, Map.class, Configuration.class)\n              .buildChecked();\n      return ctor.newInstance(rowType, writeProps, fromReadableConfig());\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  private Configuration fromReadableConfig() {\n    return readableConfig instanceof Configuration\n        ? (Configuration) readableConfig\n        : Configuration.fromMap(readableConfig.toMap());\n  }\n}\n","sourceCodeStart":275,"sourceCodeEnd":307,"githubUrl":"https://github.com/apache/iceberg/blob/86d9c8fc543e7c56c9f624eb725f76c9baff9570/flink/v2.2/flink/src/main/java/org/apache/iceberg/flink/IcebergTableSink.java#L275-L307","documentation":"IcebergTableSink.createDynamicRecordGenerator reflects over the configured DynamicRecordGeneratorSQL implementation class and throws IllegalArgumentException when the instantiated object is not assignable to the DynamicRecordGeneratorSQL interface (surfaced as ClassCastException). It means the class configured as the generator does not implement the required interface.","triggerScenarios":"Setting the sink write property that names a dynamic record generator implementation class to a class that exists and instantiates but does not implement DynamicRecordGeneratorSQL (wrong interface, wrong artifact version).","commonSituations":"Typo/mistaken class name in table properties pointing at a similar class; the class implements an older/renamed interface after an upgrade; custom generator compiled against a different Iceberg version.","solutions":["Fix the configured class name to point at a class implementing DynamicRecordGeneratorSQL.","Recompile/redeploy the custom generator against the same Iceberg Flink version.","Verify with: DynamicRecordGeneratorSQL.class.isAssignableFrom(Class.forName(impl)) before configuring."],"exampleFix":"// before\n'table.write.dynamic-record-generator' = 'com.example.MyGen' // MyGen implements some other interface\n// after\n'table.write.dynamic-record-generator' = 'com.example.MyGen' // class MyGen implements DynamicRecordGeneratorSQL { ... }","handlingStrategy":"validation","validationCode":"Class<?> c = Class.forName(generatorImpl);\nif (!DynamicRecordGeneratorSQL.class.isAssignableFrom(c)) {\n  throw new IllegalStateException(generatorImpl + \" does not implement DynamicRecordGeneratorSQL\");\n}","typeGuard":"boolean validGenerator(String name) {\n  try { return DynamicRecordGeneratorSQL.class.isAssignableFrom(Class.forName(name)); }\n  catch (ClassNotFoundException e) { return false; }\n}","tryCatchPattern":"try { sink.write(...); } catch (IllegalArgumentException e) { /* check table property 'write.dynamic-record-generator' value */ }","preventionTips":["Verify the configured class implements the interface at startup","Keep custom generators compiled against the deployed Iceberg version","Use constants for property values instead of hand-typed class names"],"tags":["flink","reflection","configuration"],"backgroundTag":"invalid-argument-value","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"}