mybatis/mybatis-3 · error · ExecutorException

Do not know how to create an instance of " + resultType

Error message

Do not know how to create an instance of " + resultType

What it means

createResultObject exhausted every strategy to instantiate the result class: it is not a simple type-handler type, has no <constructor> mappings, has no default constructor (or is an interface with no default-ctor path via metaType), and automatic constructor matching either is disabled or found no usable constructor. MyBatis therefore has no way to build an instance of resultType.

Source

Thrown at src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java:793

  private Object createResultObject(ResultSetWrapper rsw, ResultMap resultMap, List<Class<?>> constructorArgTypes,
      List<Object> constructorArgs, String columnPrefix, CacheKey parentRowKey) throws SQLException {

    final Class<?> resultType = resultMap.getType();
    final MetaClass metaType = MetaClass.forClass(resultType, reflectorFactory);
    final List<ResultMapping> constructorMappings = resultMap.getConstructorResultMappings();
    if (hasTypeHandlerForResultObject(rsw, resultType)) {
      return createPrimitiveResultObject(rsw, resultMap, columnPrefix);
    }
    if (!constructorMappings.isEmpty()) {
      return createParameterizedResultObject(rsw, resultType, constructorMappings, constructorArgTypes, constructorArgs,
          columnPrefix, resultMap.hasResultMapsUsingConstructorCollection(), parentRowKey);
    } else if (resultType.isInterface() || metaType.hasDefaultConstructor()) {
      return objectFactory.create(resultType);
    } else if (shouldApplyAutomaticMappings(resultMap, false)) {
      return createByConstructorSignature(rsw, resultMap, columnPrefix, resultType, constructorArgTypes,
          constructorArgs);
    }
    throw new ExecutorException("Do not know how to create an instance of " + resultType);
  }

  Object createParameterizedResultObject(ResultSetWrapper rsw, Class<?> resultType,
      List<ResultMapping> constructorMappings, List<Class<?>> constructorArgTypes, List<Object> constructorArgs,
      String columnPrefix, boolean useCollectionConstructorInjection, CacheKey parentRowKey) {
    boolean foundValues = false;

    for (ResultMapping constructorMapping : constructorMappings) {
      final Class<?> parameterType = constructorMapping.getJavaType();
      final String column = constructorMapping.getColumn();
      final Object value;
      try {
        if (constructorMapping.getNestedQueryId() != null) {
          value = getNestedQueryConstructorValue(rsw, constructorMapping, columnPrefix);
        } else if (JdbcType.CURSOR.equals(constructorMapping.getJdbcType())) {
          List<?> result = (List<?>) getNestedCursorValue(rsw, constructorMapping, columnPrefix).get(0);
          if (objectFactory.isCollection(parameterType)) {
            MetaObject collection = configuration.newMetaObject(objectFactory.create(parameterType));

View on GitHub (pinned to 008069adb1)

Solutions

  1. Declare constructor mapping: <constructor><arg column="..." javaType="..."/>...</constructor> in the resultMap
  2. Or add a public no-arg constructor (plus setters / automapping) to the result class
  3. Set autoMappingBehavior=PARTIAL (default) so constructor automapping can be attempted
  4. Annotate exactly one constructor with @AutomapConstructor when the class has several

Example fix

<!-- before -->
<resultMap id="userMap" type="com.example.User"/>
<!-- User only has User(Long id, String name) -->
<!-- after -->
<resultMap id="userMap" type="com.example.User">
  <constructor>
    <arg column="id" javaType="long"/>
    <arg column="name" javaType="string"/>
  </constructor>
</resultMap>
Defensive patterns

Strategy: validation

Validate before calling

// Fail fast if a resultType cannot be instantiated by any MyBatis strategy
Class<?> t = User.class;
boolean hasDefaultCtor = Arrays.stream(t.getConstructors()).anyMatch(c -> c.getParameterCount() == 0);
if (!hasDefaultCtor && !t.isInterface() && noExplicitConstructorMapping("userMap")) {
  throw new IllegalStateException(t + " needs a no-arg constructor or a <constructor> mapping");
}

Prevention

When it happens

Trigger: A resultMap whose type has only a non-empty constructor (immutable/Kotlin data class/value object), the mapping has no <constructor> block, shouldApplyAutomaticMappings is false (autoMappingBehavior=NONE) or createByConstructorSignature found no match, so the final throw executes.

Common situations: Immutable domain objects with all-args constructors and no no-arg constructor; autoMappingBehavior set to NONE globally; interfaces as resultType without a default implementation; constructor arg types not matching any sensible column set.

Related errors


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