mybatis/mybatis-3 · error · IllegalStateException
Missing resultMap in property '{}'. Parameters of type java
Error message
Missing resultMap in property '{}'. Parameters of type java.sql.ResultSet require a resultMap. What it means
ParameterMapping.Builder.validate() throws IllegalStateException when a parameter is declared with javaType=java.sql.ResultSet (an OUT cursor of a stored procedure) but no resultMapId is set. ResultSet parameters need a resultMap so MyBatis knows how to map each row of the cursor; without one, mapping is undefined and the builder refuses.
Source
Thrown at src/main/java/org/apache/ibatis/mapping/ParameterMapping.java:115
public Builder expression(String expression) {
parameterMapping.expression = expression;
return this;
}
public Builder value(Object value) {
parameterMapping.value = value;
return this;
}
public ParameterMapping build() {
validate();
return parameterMapping;
}
private void validate() {
if (ResultSet.class.equals(parameterMapping.javaType) && parameterMapping.resultMapId == null) {
throw new IllegalStateException("Missing resultMap in property '" + parameterMapping.property + "'. "
+ "Parameters of type java.sql.ResultSet require a resultMap.");
}
}
}
public String getProperty() {
return property;
}
/**
* Used for handling output of callable statements.
*
* @return the mode
*/
public ParameterMode getMode() {
return mode;
}
View on GitHub (pinned to 008069adb1)
Solutions
- Add a resultMap attribute to the CALLABLE statement that defines the mapping for the cursor rows.
- If building mappings programmatically, call .resultMapId("someResultMap") on the ParameterMapping.Builder.
- Verify the referenced resultMap id actually exists in the mapper to avoid the next failure downstream.
Example fix
<!-- before -->
<select statementType="CALLABLE" parameterType="map">
{call get_users(#{curOut,mode=OUT,javaType=java.sql.ResultSet})}
</select>
<!-- after -->
<resultMap id="userMap" type="User">
<result property="id" column="ID"/>
<result property="name" column="NAME"/>
</resultMap>
<select statementType="CALLABLE" parameterType="map" resultMap="userMap">
{call get_users(#{curOut,mode=OUT,javaType=java.sql.ResultSet})}
</select> Defensive patterns
Strategy: validation
Validate before calling
// When building callable statement parameters programmatically
if (ResultSet.class.equals(javaType) && resultMapId == null) {
throw new IllegalStateException("ResultSet parameter '" + property + "' needs a resultMap");
}
new ParameterMapping.Builder(config, property, javaType)
.mode(ParameterMode.OUT).resultMapId(resultMapId).build(); Prevention
- Treat javaType=java.sql.ResultSet OUT parameters and resultMap as a pair — always write both.
- Keep a project template for REF CURSOR calls to copy instead of hand-writing mappings.
- Integration-test stored procedure mappings against a real database; XML validation will not catch this.
When it happens
Trigger: XML like <parameter property="curOut" javaType="java.sql.ResultSet" mode="OUT"/> in a <select statementType="CALLABLE"> statement without a resultMap="..." attribute on the same statement; or ParameterMapping.Builder without .resultMapId(...) for a ResultSet javaType.
Common situations: Calling Oracle/PostgreSQL stored procedures returning REF CURSOR parameters; refactoring a statement and dropping the resultMap attribute; copy-paste of an IN-parameter mapping pattern onto a cursor OUT parameter.
Related errors
- Error resolving ParameterMode. Cause: {cause}
- Cannot open more than one iterator on a Cursor
- A Cursor is already closed.
- Cannot remove element from Cursor
- Caching stored procedures with OUT params is not supported.
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/42cdc3c69202a601.
Report an issue: GitHub.