theonedev/onedev · error · ValidationException
No value extractor found for type {type}.
Error message
No value extractor found for type {type}. What it means
Hibernate Validator throws this when cascaded validation (@Valid) reaches a container-typed value (Optional, List, Map, custom generic) but no ValueExtractor is registered that knows how to unwrap that type parameter. The framework cannot descend into the container, so it fails fast instead of silently skipping element validation.
Source
Thrown at server-core/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java:706
validateInContext( validationContext, cascadedValueContext, validationOrder );
}
private void validateCascadedContainerElementsForCurrentGroup(Object value, BaseBeanValidationContext<?> validationContext, ValueContext<?, ?> valueContext,
List<ContainerCascadingMetaData> containerElementTypesCascadingMetaData) {
for ( ContainerCascadingMetaData cascadingMetaData : containerElementTypesCascadingMetaData ) {
if ( !cascadingMetaData.isMarkedForCascadingOnAnnotatedObjectOrContainerElements() ) {
continue;
}
ValueExtractorDescriptor extractor = valueExtractorManager.getMaximallySpecificAndRuntimeContainerElementCompliantValueExtractor(
cascadingMetaData.getEnclosingType(),
cascadingMetaData.getTypeParameter(),
value.getClass(),
cascadingMetaData.getValueExtractorCandidates()
);
if ( extractor == null ) {
throw LOG.getNoValueExtractorFoundForTypeException( cascadingMetaData.getEnclosingType(), cascadingMetaData.getTypeParameter(), value.getClass() );
}
CascadingValueReceiver receiver = new CascadingValueReceiver( validationContext, valueContext, cascadingMetaData );
ValueExtractorHelper.extractValues( extractor, value, receiver );
}
}
private class CascadingValueReceiver implements ValueExtractor.ValueReceiver {
private final BaseBeanValidationContext<?> validationContext;
private final ValueContext<?, ?> valueContext;
private final ContainerCascadingMetaData cascadingMetaData;
public CascadingValueReceiver(BaseBeanValidationContext<?> validationContext, ValueContext<?, ?> valueContext, ContainerCascadingMetaData cascadingMetaData) {
this.validationContext = validationContext;
this.valueContext = valueContext;
this.cascadingMetaData = cascadingMetaData;
}View on GitHub (pinned to d44925c47c)
Solutions
- Add an @ExtractValue-annotated method (or field) to the custom container type so the framework knows which type parameter holds the validated values.
- Register a custom ValueExtractor for the container type via META-INF/services/javax.validation.valueextraction.ValueExtractor or ConstraintValidatorFactory/parameterized extractor registration.
- Remove @Valid from the field if element validation is not intended.
- Check that the same Hibernate Validator version is on the classpath at runtime as at compile time (mixed versions break extractor resolution).
Example fix
// before
class Result<T> { T value; }
@Valid Result<@NotNull String> result; // throws at validate()
// after
class Result<T> {
T value;
@ExtractValue
public T getValue() { return value; }
}
@Valid Result<@NotNull String> result; Defensive patterns
Strategy: validation
Validate before calling
// before validate(), ensure the container type has an extractor
boolean hasExtractor(Class<?> containerType, ValueExtractorRepository repo) {
return repo.getValueExtractorCandidates(containerType, TypeUseKind.CONTAINER_ELEMENT)
.size() > 0;
} Type guard
static <T> boolean isSupportedContainer(Object v) {
return v instanceof Collection || v instanceof Map || v instanceof Optional
|| v.getClass().isAnnotationPresent(ExtractValue.class)
|| java.util.Arrays.stream(v.getClass().getDeclaredMethods())
.anyMatch(m -> m.isAnnotationPresent(ExtractValue.class));
} Try / catch
try {
validator.validate(bean);
} catch (ValidationException e) {
if (e.getMessage().contains("No value extractor found")) {
// register extractor or drop @Valid on that field, then retry
} else throw e;
} Prevention
- Annotate a value-returning method with @ExtractValue on every custom container type used with @Valid.
- Prefer JDK/standard containers (List, Map, Optional) which have built-in extractors.
- Keep Hibernate Validator versions consistent across the classpath.
When it happens
Trigger: Validating a bean with @Valid on a field/parameter whose declared type is a generic container (Optional<T>, List<T>, Map<K,V>, or a custom container) for which no matching ValueExtractor exists in the registered ValueExtractorRepository — typically a custom container type without a @ExtractValue annotated method or a registered extractor.
Common situations: Upgrading Hibernate Validator (extractor discovery rules changed between 6.x versions), using Optional/Collection wrappers from third-party libraries, or defining custom generic wrapper types (e.g. a Page<T> or Result<T> class) annotated with @Valid without registering an extractor.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Error validating imported build spec (import project: %s, im
- Invalid property path: {path}.
- Unknown collection element class (bean: X, property: Y)
- Title is required
- Count should not be greater than ${RestConstants.MAX_PAGE_SI
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/86360db475577e7a.
Report an issue: GitHub.