mybatis/mybatis-3 · error · ExecutorException
The JDBC Type must be specified for output parameter. Param
Error message
The JDBC Type must be specified for output parameter. Parameter: {} What it means
For CALLABLE statements, every OUT or INOUT parameter must be registered with the driver via registerOutParameter, which requires a JDBC type. MyBatis validates this before registration: if a ParameterMapping has mode OUT/INOUT but jdbcType == null, it throws this ExecutorException naming the parameter property.
Source
Thrown at src/main/java/org/apache/ibatis/executor/statement/CallableStatementHandler.java:105
if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
return connection.prepareCall(sql);
}
return connection.prepareCall(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
@Override
public void parameterize(Statement statement) throws SQLException {
registerOutputParameters((CallableStatement) statement);
parameterHandler.setParameters((CallableStatement) statement);
}
private void registerOutputParameters(CallableStatement cs) throws SQLException {
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
for (int i = 0, n = parameterMappings.size(); i < n; i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
if (parameterMapping.getMode() == ParameterMode.OUT || parameterMapping.getMode() == ParameterMode.INOUT) {
if (null == parameterMapping.getJdbcType()) {
throw new ExecutorException(
"The JDBC Type must be specified for output parameter. Parameter: " + parameterMapping.getProperty());
}
if (parameterMapping.getNumericScale() != null && (parameterMapping.getJdbcType() == JdbcType.NUMERIC
|| parameterMapping.getJdbcType() == JdbcType.DECIMAL)) {
cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE, parameterMapping.getNumericScale());
} else {
if (parameterMapping.getJdbcTypeName() == null) {
cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE);
} else {
cs.registerOutParameter(i + 1, parameterMapping.getJdbcType().TYPE_CODE,
parameterMapping.getJdbcTypeName());
}
}
}
}
}
}View on GitHub (pinned to 008069adb1)
Solutions
- Add an explicit jdbcType to the OUT/INOUT parameter: <parameter property="result" mode="OUT" jdbcType="INTEGER"/> (or in annotations: #{result, mode=OUT, jdbcType=INTEGER}).
- If the type is driver-specific, also set typeName for named types via jdbcTypeName (e.g. Oracle STRUCT/ARRAY types).
- For INOUT parameters with null input values, always specify jdbcType so both binding and registration have a type.
Example fix
<!-- before -->
<select id="calc" statementType="CALLABLE">{ call calc(#{x, mode=INOUT}, #{total, mode=OUT}) }</select>
<!-- after -->
<select id="calc" statementType="CALLABLE">{ call calc(#{x, mode=INOUT, jdbcType=INTEGER}, #{total, mode=OUT, jdbcType=DECIMAL}) }</select> Defensive patterns
Strategy: validation
Validate before calling
// before executing, assert every OUT/INOUT parameter mapping declares a jdbcType
List<ParameterMapping> pms = boundSql.getParameterMappings();
for (ParameterMapping pm : pms) {
if ((pm.getMode() == ParameterMode.OUT || pm.getMode() == ParameterMode.INOUT)
&& pm.getJdbcType() == null) {
throw new IllegalStateException("OUT/INOUT parameter '" + pm.getProperty()
+ "' is missing jdbcType");
}
} Prevention
- Always write OUT/INOUT parameters as #{name, mode=OUT, jdbcType=...} — make it a code-review rule.
- Keep a linter/regex check over mapper XML/annotations flagging mode=(OUT|INOUT) without jdbcType.
When it happens
Trigger: Calling a stored procedure ({call ...}) with parameterMode="OUT" or "INOUT" on <parameter property="outParam" .../> (or @Param-driven parameter map) where the jdbcType attribute is missing and no default JDBC type can be inferred for null.
Common situations: Stored procedure mappings copied from IN-only examples without jdbcType; relying on defaults that exist for IN params but not OUT; NULL INOUT params where the driver cannot infer the type so MyBatis cannot fall back.
Related errors
- Parameter '{key}' not found. Available parameters are {keySe
- {methodName} cannot have multiple {paramType} parameters
- There is no getter for property named '{}' in '{}'
- Could not find type handler for Java type '" + propertyGener
- Could not set parameters for mapping: " + parameterMapping +
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/ff605369f0efdd18.
Report an issue: GitHub.