mybatis/mybatis-3 · error · BindingException

Unknown execution method for: {name}

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).

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)

Solutions

  1. Check the mapper method's matching XML/annotation and confirm the element is one of <insert>, <update>, <delete>, <select>
  2. Verify the statement id used to register the statement matches an executable element, not a <sql> fragment
  3. 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

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


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/ad5f3665c939d78e. Report an issue: GitHub.