{"record":{"id":"3c989a89c60e7661","repo":"hibernate/hibernate-orm","slug":"error-instantiating-class-using-default-const","errorCode":null,"errorMessage":"Error instantiating class '{}' using default constructor: {}","messagePattern":"Error instantiating class '(.+?)' using default constructor: (.+?)","errorType":"exception","errorClass":"InstantiationException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java","lineNumber":97,"sourceCode":"\t}\n\n\t@Override\n\tpublic JavaType<T> getAssembledJavaType() {\n\t\treturn target;\n\t}\n\n\t@Override\n\t@SuppressWarnings(\"unchecked\")\n\tpublic T assemble(RowProcessingState rowProcessingState) {\n\t\tfinal T result;\n\t\ttry {\n\t\t\tfinal var constructor = target.getJavaTypeClass().getDeclaredConstructor();\n\t\t\tconstructor.setAccessible( true );\n\t\t\tresult = constructor.newInstance();\n\t\t}\n\t\tcatch ( NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException\n\t\t\t\t| java.lang.InstantiationException e ) {\n\t\t\tthrow new InstantiationException( \"Error instantiating class '\"\n\t\t\t\t\t+ target.getTypeName() + \"' using default constructor: \" + e.getMessage(), e );\n\t\t}\n\t\tfor ( var beanInjection : beanInjections ) {\n\t\t\tfinal Object assembled = beanInjection.getValueAssembler().assemble( rowProcessingState );\n\t\t\tbeanInjection.getBeanInjector().inject( result, assembled );\n\t\t}\n\t\treturn result;\n\t}\n\n\t@Override\n\tpublic void resolveState(RowProcessingState rowProcessingState) {\n\t\tfor ( var beanInjection : beanInjections ) {\n\t\t\tbeanInjection.getValueAssembler().resolveState( rowProcessingState );\n\t\t}\n\t}\n\n\t@Override\n\tpublic <X> void forEachResultAssembler(BiConsumer<Initializer<?>, X> consumer, X arg) {","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/sql/results/graph/instantiation/internal/DynamicInstantiationAssemblerInjectionImpl.java#L79-L115","documentation":"Injection-style dynamic instantiation first creates the target instance via its declared no-arg constructor (getDeclaredConstructor() + setAccessible + newInstance) before applying bean injections. If the class has no no-arg constructor, or it cannot be invoked (private constructor in a closed module, non-static inner class requiring an enclosing instance), the reflection exception is wrapped as InstantiationException(\"Error instantiating class '<class>' using default constructor: <message>\").","triggerScenarios":"`select new com.acme.Dto(...) ...` where the injection path was chosen (no matching all-args constructor) but Dto defines only parameterized constructors; a private no-arg constructor under JPMS where setAccessible fails; a non-static inner class as the target (its hidden constructor needs the outer instance).","commonSituations":"DTOs that 'grew' an all-args constructor so the implicit default constructor disappeared; immutable-style DTOs with only final-field constructors; Kotlin data classes without a no-arg secondary constructor; Java 9+ module access rules.","solutions":["Add a public no-arg constructor to the target class (this path requires it), keeping setters/fields writable for the aliases.","If you want construction control, define an explicit constructor matching the select items - Hibernate will use the constructor path instead of injection.","For Kotlin, add a secondary constructor or apply the kotlin-noarg plugin for the DTO.","Ensure the class is a top-level or public static nested class and its package is open to reflection when running modularized."],"exampleFix":"// before\npublic class StatsDto {\n    public StatsDto(String region, Long total) { ... } // no default constructor\n}\n\n// after - keep the explicit ctor AND add the no-arg ctor for injection\npublic class StatsDto {\n    public StatsDto() { }\n    public StatsDto(String region, Long total) { ... }\n}","handlingStrategy":"validation","validationCode":"// At startup, verify the injection target has an invokable no-arg constructor\nConstructor<?> c;\ntry {\n    c = StatsDto.class.getDeclaredConstructor();\n} catch (NoSuchMethodException e) {\n    throw new IllegalStateException(\"StatsDto needs a no-arg constructor for bean-injection instantiation\", e);\n}\nif (!Modifier.isPublic(c.getModifiers()) && !c.trySetAccessible()) {\n    throw new IllegalStateException(\"no-arg constructor of StatsDto is not accessible\");\n}","typeGuard":"// Reflective guard: type is usable for injection-style instantiation\nstatic boolean hasUsableNoArgCtor(Class<?> dto) {\n    try {\n        Constructor<?> c = dto.getDeclaredConstructor();\n        return Modifier.isPublic(c.getModifiers()) || c.trySetAccessible();\n    } catch (NoSuchMethodException e) { return false; }\n}","tryCatchPattern":"try {\n    rows = q.getResultList();\n} catch (org.hibernate.query.sqm.sql.internal.InstantiationException e) {\n    if (String.valueOf(e.getMessage()).contains(\"using default constructor\")) {\n        // add a public no-arg constructor, or switch to an explicit constructor expression\n    }\n}","preventionTips":["Every bean-injection DTO gets an explicit public no-arg constructor in addition to convenience constructors.","For Kotlin DTOs, add a secondary no-arg constructor or apply the kotlin-noarg plugin.","Prefer explicit constructor expressions when you want construction to fail fast at plan build, not per row."],"tags":["hibernate","orm","dynamic-instantiation","no-arg-constructor","bean-injection","dto","reflection"],"backgroundTag":"dynamic-instantiation-no-default-constructor","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}