hibernate/hibernate-orm · error · HibernateException
Expectation.OutParameter operates exclusively on CallableSta
Error message
Expectation.OutParameter operates exclusively on CallableStatements: ${statement.getClass()} What it means
Expectations.toCallableStatement narrows the PreparedStatement handed to verifyOutcome/prepare to a CallableStatement. When the statement executed at flush time is not a CallableStatement (custom SQL not actually callable, or a programmatic call path), this HibernateException is thrown and names the statement's concrete class so you can see what the driver really produced.
Source
Thrown at hibernate-core/src/main/java/org/hibernate/jdbc/Expectations.java:60
}
private static Expectation instantiate(Supplier<? extends Expectation> supplier, boolean callable) {
if ( supplier == null ) {
return callable
? new Expectation.OutParameter()
: new Expectation.RowCount();
}
else {
return supplier.get();
}
}
static CallableStatement toCallableStatement(PreparedStatement statement) {
if ( statement instanceof CallableStatement callableStatement ) {
return callableStatement;
}
else {
throw new HibernateException( "Expectation.OutParameter operates exclusively on CallableStatements: "
+ statement.getClass() );
}
}
static void checkBatched(int expectedRowCount, int rowCount, int batchPosition, String sql) {
switch (rowCount) {
case EXECUTE_FAILED:
throw new BatchFailedException( "Batch update failed: " + batchPosition );
case SUCCESS_NO_INFO:
BATCH_MESSAGE_LOGGER.batchSuccessUnknown( batchPosition );
break;
default:
if ( expectedRowCount > rowCount ) {
throw new StaleStateException(
"Batch update returned unexpected row count from update " + batchPosition
+ actualVsExpected( expectedRowCount, rowCount )
+ " [" + sql + "]"
);View on GitHub (pinned to fad1729dce)
Solutions
- Ensure the custom SQL for the entity is declared callable = true and really is a {call ...} statement
- Confirm the driver returns a CallableStatement for the SQL (the exception prints the actual class)
- If the statement genuinely is not callable, use a COUNT or NONE expectation instead of OUT_PARAM
Example fix
// before
@SQLUpdate(sql = "update Person set name = ? where id = ?", callable = false)
@Expectation(type = ExpectationType.OUT_PARAM)
class Person { } // flush-time HibernateException: statement is not a CallableStatement
// after
@SQLUpdate(sql = "{ ? = call update_person(?, ?) }", callable = true)
@Expectation(type = ExpectationType.OUT_PARAM)
class Person { } Defensive patterns
Strategy: try-catch
Try / catch
try {
session.flush();
} catch (org.hibernate.HibernateException e) {
if (e.getMessage() != null && e.getMessage().contains("exclusively on CallableStatements")) {
// the executed statement was: e.getMessage().substring(e.getMessage().lastIndexOf(':') + 1)
// fix: mark the custom SQL callable or use a COUNT/NONE expectation
}
throw e;
} Prevention
- Never attach OUT_PARAM expectations to plain PreparedStatement custom SQL
- Verify the driver wraps {call ...} syntax in a CallableStatement before relying on out parameters
- Keep entity custom-SQL and expectations under one review unit so they change together
When it happens
Trigger: An OutParameter expectation is active but the executed statement is a plain PreparedStatement - e.g. callable flag lost on a native/programmatic path, or the driver/connection pool not wrapping {call ...} SQL in a CallableStatement.
Common situations: Same misconfiguration as the validate() MappingException but surfacing at flush instead of bootstrap (programmatic expectations, statements built outside annotation validation); unusual driver behavior wrapping callable syntax.
Related errors
- Could not extract row count from CallableStatement
- Expectation.OutParameter operates exclusively on CallableSta
- JDBC driver does not support named parameters for setArray.
- PostgreSQL only supports REF_CURSOR parameters as the first
- PostgreSQL only supports accessing REF_CURSOR parameters by
AI-assisted analysis of hibernate/hibernate-orm@fad1729dce (2026-08-22).
Data as JSON: /api/errors/a1dbbd67e8ff68dc.
Report an issue: GitHub.