mybatis/mybatis-3 · error · TypeException

Failed to invoke constructor for handler {}

Error message

Failed to invoke constructor for handler {}

What it means

The companion of error 257: a usable constructor was FOUND but invoking it failed with a ReflectiveOperationException other than NoSuchMethodException — typically an exception thrown inside the no-arg constructor, or instantiation of an abstract/classloader-hidden class. The handler class name is included in the message.

Source

Thrown at src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java:534

          return (TypeHandler<T>) c.newInstance(javaType);
        } catch (NoSuchMethodException ignored) {
        }
        if (javaType instanceof Class) {
          try {
            c = handlerClass.getConstructor(Class.class);
            return (TypeHandler<T>) c.newInstance(javaType);
          } catch (NoSuchMethodException ignored) {
          }
        }
      }
      try {
        c = handlerClass.getConstructor();
        return (TypeHandler<T>) c.newInstance();
      } catch (NoSuchMethodException e) {
        throw new TypeException("Unable to find a usable constructor for " + handlerClass, e);
      }
    } catch (ReflectiveOperationException e) {
      throw new TypeException("Failed to invoke constructor for handler " + handlerClass, e);
    }
  }

  // scan

  public void register(String packageName) {
    ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<>();
    resolverUtil.find(new ResolverUtil.IsA(TypeHandler.class), packageName);
    Set<Class<? extends Class<?>>> handlerSet = resolverUtil.getClasses();
    for (Class<?> type : handlerSet) {
      // Ignore inner classes and interfaces (including package-info.java) and abstract classes
      if (!type.isAnonymousClass() && !type.isInterface() && !Modifier.isAbstract(type.getModifiers())) {
        register(type);
      }
    }
  }

  // get information

View on GitHub (pinned to 008069adb1)

Solutions

  1. Check the Cause — if it is your own exception, move that initialization out of the constructor or make it safe
  2. Ensure the handler class is public, concrete, and visible to MyBatis' classloader
  3. Initialize expensive state lazily (on first set/get) instead of in the constructor

Example fix

// before
public MyHandler() { this.cfg = Files.readString(Path.of("/etc/app.cfg")); } // throws in prod

// after
public MyHandler() { }
private Config cfg() { return ConfigHolder.INSTANCE; } // lazy
Defensive patterns

Strategy: try-catch

Validate before calling

try {
  Object h = handlerClass.getDeclaredConstructor().newInstance(); // dry-run at registration time
} catch (ReflectiveOperationException e) {
  throw new IllegalStateException("Handler constructor failed: " + handlerClass, e);
}

Try / catch

try { registry.getInstance(type, handlerClass); } catch (TypeException e) { Throwable c = e.getCause(); // constructor body failed: inspect c and fix initialization } 

Prevention

When it happens

Trigger: A no-arg constructor that performs initialization (loading config, opening resources) and throws; handler class loaded by a different classloader triggering IllegalAccess; accidentally referencing an abstract handler class.

Common situations: Handlers that read properties/registries in their constructor; fat-jar or container classloader setups; constructor logic that depends on environment (files, env vars) absent in the current deployment.

Related errors


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