theonedev/onedev · error · ValidationException
Parameter types do not match: expected type {expected} but f
Error message
Parameter types do not match: expected type {expected} but found {actual} for parameter index {index} of {executable}. What it means
Thrown during executable parameter validation when a supplied argument value's runtime type cannot be assigned to the declared parameter type (after considering unboxing of primitive wrappers). The validator rejects the invocation rather than validating values against constraints for incompatible types.
Source
Thrown at server-core/src/main/java/org/hibernate/validator/internal/engine/ValidatorImpl.java:1036
ValueContext<T, Object> valueContext = getExecutableValueContext(
validationContext.getRootBean(), executableMetaData, executableMetaData.getValidatableParametersMetaData(), currentValidatedGroup
);
// 2. validate parameter constraints
for ( int i = 0; i < parameterValues.length; i++ ) {
ParameterMetaData parameterMetaData = executableMetaData.getParameterMetaData( i );
Object value = parameterValues[i];
if ( value != null ) {
Class<?> valueType = value.getClass();
if ( parameterMetaData.getType() instanceof Class && ( (Class<?>) parameterMetaData.getType() ).isPrimitive() ) {
valueType = ReflectionHelper.unBoxedType( valueType );
}
if ( !TypeHelper.isAssignable(
TypeHelper.getErasedType( parameterMetaData.getType() ),
valueType
) ) {
throw LOG.getParameterTypesDoNotMatchException(
valueType,
parameterMetaData.getType(),
i,
validationContext.getExecutable()
);
}
}
validateMetaConstraints( validationContext, valueContext, parameterValues, parameterMetaData );
if ( shouldFailFast( validationContext ) ) {
return;
}
}
}
private <T> ValueContext<T, Object> getExecutableValueContext(T object, ExecutableMetaData executableMetaData, Validatable validatable, Class<?> group) {
ValueContext<T, Object> valueContext;
View on GitHub (pinned to d44925c47c)
Solutions
- Ensure each supplied value matches the declared parameter type at the matching index (convert/coerce before calling validateParameters).
- Verify the parameter order — a transposition often causes index/type mismatch.
- For primitive parameters pass the boxed wrapper (Integer for int); the validator unboxes it, but a wrong wrapper (Long for int) is rejected.
- Use the executable's actual parameter types (getParameterTypes()) instead of assumed types when building the array.
Example fix
// before
Object[] args = { String.valueOf(userId) }; // userId param is Long
validator.forExecutables().validateParameters(service, method, args);
// after
Object[] args = { Long.valueOf(userId) };
validator.forExecutables().validateParameters(service, method, args); Defensive patterns
Strategy: validation
Validate before calling
for (int i = 0; i < args.length; i++) {
Class<?> p = method.getParameterTypes()[i];
Object v = args[i];
boolean ok = v == null || p.isInstance(v)
|| (p.isPrimitive() && isBoxCompatible(p, v.getClass()));
if (!ok) throw new IllegalArgumentException(
"arg " + i + " type " + v.getClass() + " not assignable to " + p);
} Type guard
static boolean matchesParam(Object value, Class<?> paramType) {
if (value == null) return !paramType.isPrimitive();
Class<?> boxed = paramType.isPrimitive()
? MethodHandles.lookup().findConstructor(
boxFor(paramType), methodType(void.class, paramType)) != null
? boxFor(paramType) : Object.class
: paramType;
return boxed.isInstance(value);
} Try / catch
try {
validator.forExecutables().validateParameters(target, method, args);
} catch (ValidationException e) {
if (e.getMessage().startsWith("Parameter types do not match")) {
// coerce arg types per method.getGenericParameterTypes() and retry
} else throw e;
} Prevention
- Build argument arrays using each declared parameter type (convert/coerce explicitly).
- For primitives, pass the correct wrapper (Integer for int, not Long).
- Beware boxing: Integer and Long are never interchangeable for primitive params.
When it happens
Trigger: validateParameters called with an Object[] where element i is not an instance of (or assignable to, incl. autoboxing) executableMetaData.getParameterTypes()[i] — e.g. passing a String where an Integer parameter is declared, or passing null-typed generics/wrapped values that lost their type at runtime.
Common situations: Building argument arrays reflectively (from request maps, JSON, or framework dispatchers), refactoring parameter types without updating callers, autoboxing assumptions with primitive parameters.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Invalid parameter count for executable {executable}: expecte
- Invalid element type:
- Getter not found for property: ${propertyName}
- Getter not found for property: ${dependsOn.property()}
- Error invoking getter for property: ${dependsOn.property()}
AI-assisted analysis of theonedev/onedev@d44925c47c (2026-09-06).
Data as JSON: /api/errors/e93bf281fa6e8a0b.
Report an issue: GitHub.