hibernate/hibernate-orm · error · HibernateException

jakarta.persistence.validation.group.{} is of unknown type:

Error message

jakarta.persistence.validation.group.{} is of unknown type: String or Class<?>[] only

What it means

The value of a jakarta.persistence.validation.group.* property must be either a String (comma-separated class names) or a Class<?>[] / single Class when configuring programmatically. Anything else — List, Set, Properties, Optional — falls through the type checks and hits the final branch, throwing this HibernateException naming the exact property key.

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/beanvalidation/GroupsPerOperation.java:97

			}

			final List<Class<?>> groupsList = new ArrayList<>( groupNames.length );
			for ( String groupName : groupNames ) {
				final String cleanedGroupName = groupName.trim();
				if ( !cleanedGroupName.isEmpty() ) {
					try {
						groupsList.add( classLoaderAccess.classForName( cleanedGroupName ) );
					}
					catch ( ClassLoadingException e ) {
						throw new HibernateException( "Unable to load class " + cleanedGroupName, e );
					}
				}
			}
			return groupsList.toArray( new Class<?>[0] );
		}

		//null is bad and excluded by instanceof => exception is raised
		throw new HibernateException( JAKARTA_JPA_GROUP_PREFIX
				+ operation.getJakartaGroupPropertyName()
				+ " is of unknown type: String or Class<?>[] only");
	}

	public Class<?>[] get(Operation operation) {
		return groupsPerOperation.get( operation );
	}

	public enum Operation {
		PERSIST( "persist", JPA_GROUP_PREFIX + "pre-persist", JAKARTA_JPA_GROUP_PREFIX + "pre-persist" ),
		MERGE( "merge", JAKARTA_JPA_GROUP_PREFIX + "pre-merge", JAKARTA_JPA_GROUP_PREFIX + "pre-merge" ),
		REMOVE( "remove", JPA_GROUP_PREFIX + "pre-remove", JAKARTA_JPA_GROUP_PREFIX + "pre-remove" ),
		INSERT( "insert", JAKARTA_JPA_GROUP_PREFIX + "pre-insert", JAKARTA_JPA_GROUP_PREFIX + "pre-insert", true ),
		UPDATE( "update", JPA_GROUP_PREFIX + "pre-update", JAKARTA_JPA_GROUP_PREFIX + "pre-update", true ),
		UPSERT( "upsert", JAKARTA_JPA_GROUP_PREFIX + "pre-upsert", JAKARTA_JPA_GROUP_PREFIX + "pre-upsert", true ),
		DELETE( "delete", JAKARTA_JPA_GROUP_PREFIX + "pre-delete", JAKARTA_JPA_GROUP_PREFIX + "pre-delete" ),
		DDL( "ddl", HIBERNATE_GROUP_PREFIX + "ddl", HIBERNATE_GROUP_PREFIX + "ddl", true );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Pass a single comma-separated String value for the group property
  2. When configuring programmatically, pass Class<?>[] or a Class instance instead of names
  3. For Spring Boot YAML, use a scalar string value, not a YAML list

Example fix

// before
Map<String,Object> settings = new HashMap<>();
settings.put("jakarta.persistence.validation.group.pre-persist",
            List.of("com.a.G1", "com.b.G2")); // List -> rejected at boot

// after
settings.put("jakarta.persistence.validation.group.pre-persist", "com.a.G1,com.b.G2");
Defensive patterns

Strategy: type-guard

Validate before calling

// normalize the value before it reaches Hibernate
static Object sanitizeGroupValue(Object value) {
    if (value instanceof String || value instanceof Class<?>[] || value instanceof Class<?>) return value;
    if (value instanceof Collection<?> c)
        return c.stream().map(String::valueOf).collect(java.util.stream.Collectors.joining(","));
    throw new IllegalArgumentException(
        "validation group value must be a comma-separated String or Class<?>[] but was "
        + (value == null ? "null" : value.getClass().getName()));
}

Type guard

static boolean isValidGroupSetting(Object value) {
    return value instanceof String || value instanceof Class<?>[] || value instanceof Class<?>;
}

Try / catch

try {
    sessionFactory = configuration.buildSessionFactory();
} catch (HibernateException e) {
    if (e.getMessage().contains("is of unknown type: String or Class<?>[] only"))
        throw new IllegalStateException("Validation group property must be a String or Class<?>[]", e);
    throw e;
}

Prevention

When it happens

Trigger: Building a SessionFactory with Map-based settings where a validation group property is bound to a java.util.List (typical when Spring Boot maps a YAML list into jpaProperties) or any non-String, non-Class collection value.

Common situations: Spring Boot application.yml lists bound to map values; configuration DSLs that store collections by default; copying list-style config from other frameworks.

Related errors


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