{"record":{"id":"074074a416a104a6","repo":"apache/flink","slug":"could-not-find-record-canonical-constructor","errorCode":null,"errorMessage":"Could not find record canonical constructor","messagePattern":"Could not find record canonical constructor","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/JavaRecordBuilderFactory.java","lineNumber":168,"sourceCode":"                            field == null ? -1 : componentNames.indexOf(fields[i].getName());\n                }\n\n                // We have to initialize newly added primitive fields to their correct default value\n                Object[] defaultValues = new Object[componentNames.size()];\n                for (int i = 0; i < componentNames.size(); i++) {\n                    Class<?> fieldType = componentTypes[i];\n                    boolean newPrimitive =\n                            fieldType.isPrimitive()\n                                    && !previousFields.contains(componentNames.get(i));\n                    defaultValues[i] = newPrimitive ? Defaults.defaultValue(fieldType) : null;\n                }\n                return new JavaRecordBuilderFactory<>(\n                        recordConstructor, argIndexMapping, defaultValues);\n            } else {\n                return new JavaRecordBuilderFactory<>(recordConstructor);\n            }\n        } catch (Exception e) {\n            throw new RuntimeException(\"Could not find record canonical constructor\", e);\n        }\n    }\n}\n","sourceCodeStart":150,"sourceCodeEnd":172,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-core/src/main/java/org/apache/flink/api/java/typeutils/runtime/JavaRecordBuilderFactory.java#L150-L172","documentation":"Thrown by JavaRecordBuilderFactory.create() when the reflective lookup of a record's canonical constructor fails. The lookup calls Class.getRecordComponents() reflectively and clazz.getDeclaredConstructor(componentTypes); any failure (class is not a record, JDK too old, inaccessible class, constructor signature mismatch) is wrapped in this RuntimeException.","triggerScenarios":"Calling create(clazz, fields) where clazz is not a java.lang.Record (e.g. a POJO or a class compiled to an interface via -parameters quirks); running on a JVM that lacks record support (< Java 16); record components changed so getDeclaredConstructor(componentTypes) finds no exact match; record/classloader inaccessibility despite setAccessible(true).","commonSituations":"TypeInformation mistakenly classified a plain class as a record; running Flink user code on Java 11 where getRecordComponents does not exist; modules/JPMS denies deep reflection on the record package; upgrading a record's component types breaks restore from an old serializer snapshot.","solutions":["Verify the class is a real record: Class.isRecord() (and run on Java 16+ for full record support)","Check the cause chain - a NoSuchMethodException means component types in the canonical constructor no longer match getRecordComponents() output","Ensure the record's package is opened/exported to Flink's user-code classloader under JPMS","If the type is not meant to be a record, fix type extraction so POJO serialization is used instead"],"exampleFix":"// before\nObject factory = JavaRecordBuilderFactory.create(someClass, fields);\n\n// after\nif (!someClass.isRecord()) {\n    throw new IllegalArgumentException(someClass + \" is not a record\");\n}\nObject factory = JavaRecordBuilderFactory.create(someClass, fields);","handlingStrategy":"validation","validationCode":"if (!clazz.isRecord()) {\n    throw new IllegalArgumentException(clazz + \" is not a record; use POJO serialization\");\n}\n// also requires Java 16+ runtime\nif (!Class.class.getMethods().toString().isEmpty() && Runtime.version().feature() < 16) {\n    throw new IllegalStateException(\"Records require Java 16+\");\n}","typeGuard":"static boolean isRecordClass(Class<?> c) {\n    return c != null && c.isRecord();\n}","tryCatchPattern":"try {\n    factory = JavaRecordBuilderFactory.create(clazz, fields);\n} catch (RuntimeException e) {\n    throw new IllegalArgumentException(\"Cannot build record factory for \" + clazz + \": \" + e.getCause(), e);\n}","preventionTips":["Run user code containing records on Java 16 or newer","Open the record's package to Flink's classloader under JPMS","Keep record component names/order aligned with serialized field lists during schema evolution"],"tags":["serialization","records","reflection","classloader"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}