mybatis/mybatis-3 · error · BindingException
Unknown execution method for
Error message
Unknown execution method for: {name} What it means
Thrown at the default branch of MapperMethod.execute() when the mapped statement's SqlCommandType does not match any of the handled cases (INSERT, UPDATE, DELETE, SELECT, FLUSH). It means MyBatis resolved the statement but its declared command type is something the executor cannot dispatch on. In practice this surfaces as UNKNOWN statement types (e.g. a <sql> fragment misregistered, or custom statement types from Configuration extensions).
Solutions
- Check the mapper method's matching XML/annotation and confirm the element is one of <insert>, <update>, <delete>, <select>
- Verify the statement id used to register the statement matches an executable element, not a <sql> fragment
- If using a custom Configuration/builder, ensure it sets a standard SqlCommandType when building MappedStatement
Example fix
<!-- before -->
<sql id="findById">SELECT * FROM t WHERE id = #{id}</sql>
<!-- after -->
<select id="findById" resultType="T">SELECT * FROM t WHERE id = #{id}</select> Defensive patterns
Strategy: validation
Validate before calling
Set<?> execTypes = Set.of(SqlCommandType.INSERT, SqlCommandType.UPDATE, SqlCommandType.DELETE, SqlCommandType.SELECT, SqlCommandType.FLUSH);
MappedStatement ms = sqlSessionFactory.getConfiguration().getMappedStatement("com.example.UserMapper.find");
if (!execTypes.contains(ms.getSqlCommandType())) {
throw new IllegalStateException("Non-executable statement type: " + ms.getSqlCommandType());
} Try / catch
catch (BindingException e) when starting up: fail configuration fast and log command type; no runtime retry is meaningful.
Prevention
- Standardize on <select>/<insert>/<update>/<delete> elements only
- Run a startup smoke test invoking each mapper method once against a test Configuration
When it happens
Trigger: Calling a mapper method whose MappedStatement.getSqlCommandType() returns a type outside {INSERT, UPDATE, DELETE, SELECT, FLUSH}; typically a statement parsed with an unknown sqlCommandType attribute or produced by a custom builder.
Common situations: Custom Configuration subclasses registering statements with exotic types; corrupted or hand-built MappedStatement objects; edge cases where a statement id collides with a non-executable element.
Related errors
- A query was run and no Result Maps were found for the…
- Error getting mapper instance. Cause
- Invalid bound statement (not found)
- JDBC requires that the JdbcType must be specified for all…
- Mapper method ' ' attempted to return null from a method…
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/ad5f3665c939d78e.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/org/apache/ibatis/binding/MapperMethod.java:97
} else if (method.returnsMany()) {
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
result = executeForCursor(sqlSession, args);
} else {
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ "' attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
private Object rowCountResult(int rowCount) {
final Object result;
if (method.returnsVoid()) {
result = null;
} else if (Integer.class.equals(method.getReturnType()) || Integer.TYPE.equals(method.getReturnType())) {
result = rowCount;
} else if (Long.class.equals(method.getReturnType()) || Long.TYPE.equals(method.getReturnType())) {
result = (long) rowCount;
} else if (Boolean.class.equals(method.getReturnType()) || Boolean.TYPE.equals(method.getReturnType())) {
result = rowCount > 0;View on GitHub (pinned to 008069adb1)