hibernate/hibernate-orm · error · IllegalArgumentException

Could not determine the record components for: " + javaType.

Error message

Could not determine the record components for: " + javaType.getName()

What it means

ReflectHelper.getRecordComponentTypes(Class) reflects over a Java record to return its component types. Anything that fails inside is caught and rethrown as IllegalArgumentException with this message, so the real reason rides on getCause(). The most common cause is javaType.getRecordComponents() returning null because the class is not actually a record; a SecurityException denying reflective access is the other path.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/internal/util/ReflectHelper.java:858

		return null;
	}

	@Deprecated(forRemoval = true)
	public static boolean isRecord(Class<?> declaringClass) {
		return declaringClass.isRecord();
	}

	public static Class<?>[] getRecordComponentTypes(Class<?> javaType) {
		try {
			final var recordComponents = javaType.getRecordComponents();
			final var componentTypes = new Class[recordComponents.length];
			for (int i = 0; i < recordComponents.length; i++ ) {
				componentTypes[i] = recordComponents[i].getType();
			}
			return componentTypes;
		}
		catch (Exception e) {
			throw new IllegalArgumentException(
					"Could not determine the record components for: " + javaType.getName(),
					e
			);
		}
	}

	public static String[] getRecordComponentNames(Class<?> javaType) {
		try {
			final var recordComponents = javaType.getRecordComponents();
			final var componentNames = new String[recordComponents.length];
			for (int i = 0; i < recordComponents.length; i++ ) {
				componentNames[i] = recordComponents[i].getName();
			}
			return componentNames;
		}
		catch (Exception e) {
			throw new IllegalArgumentException(
					"Could not determine the record components for: " + javaType.getName(),

View on GitHub (pinned to fad1729dce)

Solutions

  1. Check the class with Class.isRecord(); if false, convert it to a real Java record or map it as a normal embeddable class.
  2. Clean and rebuild so the record-compiled version of the class is the one actually on the runtime classpath.
  3. Read getCause() to separate 'not a record' (NullPointerException) from access denial (SecurityException) and fix accordingly.

Example fix

// before: plain class where record semantics are assumed
public class Money {
    private final BigDecimal amount;
    public Money(BigDecimal amount) { this.amount = amount; }
    public BigDecimal amount() { return amount; }
}

// after
public record Money(BigDecimal amount) {}
Defensive patterns

Strategy: type-guard

Validate before calling

static void requireRecord(Class<?> cls) {
    if (cls == null || !cls.isRecord()) {
        throw new IllegalArgumentException("Not a java record: " + cls);
    }
}

Type guard

static boolean isRecord(Class<?> cls) {
    return cls != null && cls.isRecord();
}

Try / catch

try {
    Class<?>[] types = ReflectHelper.getRecordComponentTypes(cls);
} catch (IllegalArgumentException e) {
    // e.getCause(): NullPointerException -> cls is not a record; SecurityException -> access denied
}

Prevention

When it happens

Trigger: Passing a class that is not a java.lang.Record (plain class, enum, interface, abstract class) to getRecordComponentTypes — getRecordComponents() returns null, the subsequent array access throws NullPointerException, and the catch wraps it. Also triggered when a security manager or module boundary denies access to record components.

Common situations: An @Embeddable or composite id expected to be a record but declared as a regular class; Kotlin/Scala/Groovy classes mistaken for JVM records; stale compiled class on the classpath predating a record conversion; instrumentation tools stripping the record flag.

Related errors


AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22). Data as JSON: /api/errors/aa445eff40e2150c. Report an issue: GitHub.