spring-projects/spring-framework · error · IllegalStateException
Failed to find Java constructor for Kotlin primary construct
Error message
Failed to find Java constructor for Kotlin primary constructor: ${clazz.getName()} What it means
Thrown inside the private KotlinDelegate.findPrimaryConstructor (IllegalStateException) when the class is detected as Kotlin and a primary constructor exists, but kotlin.reflect.jvm.ReflectJvmMapping.getJavaConstructor returned null - the Kotlin-to-Java constructor mapping could not be resolved. This is an internal Spring failure to bridge Kotlin reflection to a Java Constructor, surfaced when BeanUtils.instantiateClass resolves constructor args for a Kotlin bean.
Source
Thrown at spring-beans/src/main/java/org/springframework/beans/BeanUtils.java:889
* https://kotlinlang.org/docs/reference/classes.html#constructors</a>
*/
@SuppressWarnings("unchecked")
public static <T> @Nullable Constructor<T> findPrimaryConstructor(Class<T> clazz) {
try {
KClass<T> kClass = JvmClassMappingKt.getKotlinClass(clazz);
KFunction<T> primaryCtor = KClasses.getPrimaryConstructor(kClass);
if (primaryCtor == null) {
return null;
}
if (KotlinDetector.isInlineClass(clazz)) {
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
Assert.state(constructors.length == 1,
"Kotlin value classes annotated with @JvmInline are expected to have a single JVM constructor");
return (Constructor<T>) constructors[0];
}
Constructor<T> constructor = ReflectJvmMapping.getJavaConstructor(primaryCtor);
if (constructor == null) {
throw new IllegalStateException(
"Failed to find Java constructor for Kotlin primary constructor: " + clazz.getName());
}
return constructor;
}
catch (UnsupportedOperationException ex) {
return null;
}
}
/**
* Instantiate a Kotlin class using the provided constructor.
* @param ctor the constructor of the Kotlin class to instantiate
* @param args the constructor arguments to apply
* (use {@code null} for unspecified parameter if needed)
*/
public static <T> T instantiateClass(Constructor<T> ctor, @Nullable Object... args)
throws IllegalAccessException, InvocationTargetException, InstantiationException {
View on GitHub (pinned to e8729d0438)
Solutions
- Ensure kotlin-reflect version exactly matches the Kotlin stdlib version used to compile the class.
- If the class does not need primary-constructor resolution, annotate it with a plain Java-style constructor or @JvmOverloads so Spring falls back to Java resolution.
- Disable bytecode shrinking/obfuscation for Kotlin metadata, or add keep rules for constructors.
- Report to Spring if reproducible with aligned versions - getJavaConstructor returning null for a valid primary constructor is a bridge bug.
Example fix
// before: kotlin-reflect 1.6 on classpath, bean compiled with Kotlin 1.9 implementation "org.jetbrains.kotlin:kotlin-reflect:1.6.21" // after: align reflect to the compiler implementation "org.jetbrains.kotlin:kotlin-reflect:1.9.24" implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.24"
Defensive patterns
Strategy: validation
Validate before calling
// Confirm kotlin-reflect is present and version-aligned before instantiation
try {
Class<?> kd = Class.forName("kotlin.reflect.jvm.ReflectJvmMapping");
// optionally compare KotlinVersion to compiled metadata
} catch (ClassNotFoundException e) {
throw new IllegalStateException("kotlin-reflect missing on classpath");
}
Constructor<?> c = BeanUtils.findPrimaryConstructor(clazz);
if (c == null) {
// fall back: use a declared constructor explicitly
c = clazz.getDeclaredConstructors()[0];
} Type guard
// Verify the class actually has a resolvable Java constructor before Spring touches it
static boolean isKotlinBeanInstantiable(Class<?> clazz) {
if (!KotlinDetector.isKotlinPresent() || !KotlinDetector.isKotlinType(clazz)) return true;
Constructor<?> c = BeanUtils.findPrimaryConstructor(clazz);
return c != null;
} Try / catch
try {
Constructor<T> ctor = BeanUtils.findPrimaryConstructor(clazz);
return BeanUtils.instantiateClass(ctor == null ? clazz.getDeclaredConstructor() : ctor);
} catch (IllegalStateException ex) {
if (ex.getMessage().contains("Failed to find Java constructor for Kotlin")) {
// fall back to a manually chosen declared constructor
Constructor<T> fallback = clazz.getDeclaredConstructors()[0];
ReflectionUtils.makeAccessible(fallback);
return fallback.newInstance();
}
throw ex;
} Prevention
- Pin kotlin-reflect to the exact Kotlin stdlib version used to compile the beans.
- Add ProGuard/R8 keep rules for Kotlin metadata and constructors.
- Annotate Kotlin beans with @JvmOverloads or explicit Java constructors when they must be reflectively instantiated.
- Test Spring instantiation of every Kotlin bean in a focused unit test.
When it happens
Trigger: BeanUtils.findPrimaryConstructor(clazz) on a Kotlin class whose primary constructor is present in Kotlin metadata but has no resolvable Java Constructor (obfuscated bytecode, unusual compiler-generated synthetic constructors, mismatched kotlin-reflect runtime version vs. the Kotlin compiler that produced the class).
Common situations: Upgrading the Kotlin compiler without bumping kotlin-reflect on the classpath; R8/ProGuard stripping the constructor metadata; Kotlin classes compiled with experimental language versions; Spring trying to autowire a Kotlin data class when kotlin-reflect is missing or a different version.
Related errors
- No default constructor found
- Illegal arguments for constructor
- Could not copy property '${targetPd.getName()}' from source
- Field is not accessible
- Service locator exception [{}] neither has a (String, Throwa
AI-assisted analysis of spring-projects/spring-framework@e8729d0438 (2026-08-04).
Data as JSON: /data/errors/86c95a01a93e095f.json.
Report an issue: GitHub.