hibernate/hibernate-orm · error · UnsupportedOperationException
Type [${userType}] does support parameter value extraction
Error message
Type [${userType}] does support parameter value extraction What it means
CustomType.extract(CallableStatement, int, session) (CustomType.java:327-341) throws UnsupportedOperationException when canDoExtraction() is false, i.e. the wrapped UserType does not implement ProcedureParameterExtractionAware (or its canDoExtraction() returns false). Extraction-by-position is what backs StoredProcedureQuery.getOutputParameterValue(int) for OUT/INOUT parameters, so reading an output parameter typed with a plain UserType fails.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/type/CustomType.java:339
}
}
@Override
public boolean canDoExtraction() {
return getUserType() instanceof ProcedureParameterExtractionAware<?> procedureParameterExtractionAware
&& procedureParameterExtractionAware.canDoExtraction();
}
@Override
public J extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session)
throws SQLException {
if ( canDoExtraction() ) {
//noinspection unchecked
return ((ProcedureParameterExtractionAware<J>) getUserType() )
.extract( statement, startIndex, session );
}
else {
throw new UnsupportedOperationException(
"Type [" + getUserType() + "] does support parameter value extraction"
);
}
}
@Override
public J extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session)
throws SQLException {
if ( canDoExtraction() ) {
//noinspection unchecked
return ((ProcedureParameterExtractionAware<J>) getUserType() )
.extract( statement, paramName, session );
}
else {
throw new UnsupportedOperationException(
"Type [" + getUserType() + "] does support parameter value extraction"
);
}View on GitHub (pinned to fad1729dce)
Solutions
- Implement ProcedureParameterExtractionAware on the UserType: add extract(CallableStatement, int, SharedSessionContract) and return true from canDoExtraction().
- If the type cannot be changed, register the parameter as a basic type (e.g. String) and convert the returned value yourself.
- Check INOUT parameters too - they also pass through extraction after execution.
- Keep positional and named extract implementations consistent if you support both call styles.
Example fix
// before
public class JsonUserType implements UserType<Payload> { /* no extraction support */ }
// after
public class JsonUserType implements UserType<Payload>, ProcedureParameterExtractionAware<Payload> {
@Override public boolean canDoExtraction() { return true; }
@Override public Payload extract(CallableStatement statement, int startIndex,
SharedSessionContract session) throws SQLException {
String json = statement.getString(startIndex);
return json == null ? null : parse(json);
}
@Override public Payload extract(CallableStatement statement, String paramName,
SharedSessionContract session) throws SQLException {
String json = statement.getString(paramName);
return json == null ? null : parse(json);
}
// ... rest of UserType
} Defensive patterns
Strategy: type-guard
Validate before calling
UserType<?> t = resolveUserType(paramType);
if (!(t instanceof org.hibernate.usertype.ProcedureParameterExtractionAware<?> ea)
|| !ea.canDoExtraction()) {
// read as String/basic and convert, instead of getOutputParameterValue(int)
String raw = (String) query.getOutputParameterValue(index);
return parse(raw);
} Type guard
static boolean supportsExtraction(UserType<?> t) {
return t instanceof org.hibernate.usertype.ProcedureParameterExtractionAware<?> ea
&& ea.canDoExtraction();
} Try / catch
try {
return (Money) query.getOutputParameterValue(index);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("parameter value extraction")) {
return parse((String) query.getOutputParameterValue(index));
}
throw e;
} Prevention
- Treat ProcedureParameterExtractionAware as part of the definition-of-done for any UserType used in callable statements.
- Read OUT parameters of unsupported custom types through a basic-typed registration and convert at the call site.
When it happens
Trigger: StoredProcedureQuery.registerStoredProcedureParameter(i, MyCustomType.class, ParameterMode.OUT) followed by getOutputParameterValue(i), where the custom type does not implement org.hibernate.usertype.ProcedureParameterExtractionAware; also frameworks that reflectively read all output parameters after executing a call.
Common situations: Custom types for JSONB/enum/monetary columns reused as procedure OUT parameters; migrating from direct JDBC calls (which handled extraction manually) to JPA StoredProcedureQuery; upgrading Hibernate versions where extraction was previously never invoked for these types.
Related errors
- Type [${userType}] does support parameter binding by name
- Class '" + typeName + "' does not implement '" + supertype.g
- IN parameter not valid for output extraction
- Parameter [" + parameter + "] is not registered with this pr
- Error extracting procedure output parameter value [" + param
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/3302f92305796249.
Report an issue: GitHub.