hibernate/hibernate-orm · error · ConstraintViolationException

Validation failed for classes {} during {} time for groups [

Error message

Validation failed for classes {} during {} time for groups [{}]
List of constraint violations:[
{}
]

What it means

BeanValidationEventListener runs Jakarta Validation before each pre-persist/pre-update/pre-remove entity event, using the groups configured per operation (jakarta.persistence.validation.group.pre-*). When the Validator returns any violation, Hibernate throws jakarta.validation.ConstraintViolationException whose message lists the failing classes, the operation, the groups, and each violation; the full violation set is available via getConstraintViolations().

Source

Thrown at hibernate-core/src/main/java/org/hibernate/boot/beanvalidation/BeanValidationEventListener.java:173

				GroupsPerOperation.Operation.UPDATE
		);
	}

	private <T> void validate(T object, EntityPersister persister, GroupsPerOperation.Operation operation) {
		if ( object != null && persister.getRepresentationStrategy().getMode() == POJO ) {
			final var groups = groupsPerOperation.get( operation );
			if ( groups.length > 0 ) {
				final var constraintViolations = validator.validate( object, groups );
				if ( !constraintViolations.isEmpty() ) {
					final Set<ConstraintViolation<?>> propagatedViolations =
							setOfSize( constraintViolations.size() );
					final Set<String> classNames = new HashSet<>();
					for ( var violation : constraintViolations ) {
						BEAN_VALIDATION_LOGGER.trace( violation );
						propagatedViolations.add( violation );
						classNames.add( violation.getLeafBean().getClass().getName() );
					}
					throw new ConstraintViolationException(
							message( operation, classNames, groups, constraintViolations ),
							propagatedViolations );
				}
			}
		}
	}

	private <T> String message(
			GroupsPerOperation.Operation operation,
			Set<String> classNames,
			Class<?>[] groups,
			Set<ConstraintViolation<T>> constraintViolations) {
		final var builder = new StringBuilder();
		builder.append( "Validation failed for classes " )
				.append( classNames )
				.append( " during " )
				.append( operation.getName() )
				.append( " time for groups [" );

View on GitHub (pinned to fad1729dce)

Solutions

  1. Inspect e.getConstraintViolations() and fix the offending property values before saving
  2. Adjust the constraint (or move it to a different validation group) if the rule itself is wrong
  3. If the field is legitimately optional at this lifecycle stage, validate it in a later-phase group instead of the default one
  4. As a last resort set validation-mode NONE or jakarta.persistence.validation.mode=none — but never in production just to hide data bugs

Example fix

// before
em.persist(new User(null, "jdoe")); // User.name is @NotNull -> ConstraintViolationException at pre-persist

// after
em.persist(new User("John Doe", "jdoe"));
Defensive patterns

Strategy: try-catch

Validate before calling

// run the same validation Hibernate would, before touching the EntityManager
Set<ConstraintViolation<MyEntity>> violations = validator.validate(entity);
if (!violations.isEmpty()) {
    throw new IllegalArgumentException("Entity invalid: " + violations);
}
em.persist(entity);

Try / catch

try {
    em.persist(entity);
    em.flush();
} catch (jakarta.validation.ConstraintViolationException e) {
    Map<String, String> errors = e.getConstraintViolations().stream()
        .collect(Collectors.toMap(
            v -> v.getPropertyPath().toString(),
            ConstraintViolation::getMessage));
    throw new BadRequestException(errors); // map to a user-facing error; never swallow silently
}

Prevention

When it happens

Trigger: Calling persist()/merge()/remove() (including cascades) on an entity whose state violates its constraints — a @NotNull field set to null, @Size/@Pattern violated, @Min/@Max out of range — while the SessionFactory runs with validation mode CALLBACK (the Jakarta default) or AUTO with a provider present.

Common situations: Saving partially populated objects mapped as entities; frontend or batch jobs bypassing the API layer's validation; a constraint tightened later (field newly @NotNull) while existing data flows still send null; @Valid cascades revealing violations on embedded objects.

Related errors


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