{"record":{"id":"0ca817be59a68a1f","repo":"mybatis/mybatis-3","slug":"type-typehandlertype-is-not-a-valid-typehandler","errorCode":null,"errorMessage":"Type {typeHandlerType} is not a valid TypeHandler because it does not implement TypeHandler interface","messagePattern":"Type (.+?) is not a valid TypeHandler because it does not implement TypeHandler interface","errorType":"exception","errorClass":"BuilderException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/builder/BaseBuilder.java","lineNumber":122,"sourceCode":"      throw new BuilderException(\"Error resolving class. Cause: \" + e, e);\n    }\n  }\n\n  @Deprecated(since = \"3.6.0\", forRemoval = true)\n  protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, String typeHandlerAlias) {\n    return resolveTypeHandler(javaType, null, typeHandlerAlias);\n  }\n\n  @Deprecated(since = \"3.6.0\", forRemoval = true)\n  protected TypeHandler<?> resolveTypeHandler(Class<?> javaType, Class<? extends TypeHandler<?>> typeHandlerType) {\n    return resolveTypeHandler(javaType, null, typeHandlerType);\n  }\n\n  protected TypeHandler<?> resolveTypeHandler(Type propertyType, JdbcType jdbcType, String typeHandlerAlias) {\n    Class<? extends TypeHandler<?>> typeHandlerType = null;\n    typeHandlerType = resolveClass(typeHandlerAlias);\n    if (typeHandlerType != null && !TypeHandler.class.isAssignableFrom(typeHandlerType)) {\n      throw new BuilderException(\"Type \" + typeHandlerType.getName()\n          + \" is not a valid TypeHandler because it does not implement TypeHandler interface\");\n    }\n    return resolveTypeHandler(propertyType, jdbcType, typeHandlerType);\n  }\n\n  protected TypeHandler<?> resolveTypeHandler(Type javaType, JdbcType jdbcType,\n      Class<? extends TypeHandler<?>> typeHandlerType) {\n    if (typeHandlerType == null && jdbcType == null) {\n      return null;\n    }\n    return configuration.getTypeHandlerRegistry().getTypeHandler(javaType, jdbcType, typeHandlerType);\n  }\n\n  protected <T> Class<? extends T> resolveAlias(String alias) {\n    return typeAliasRegistry.resolveAlias(alias);\n  }\n}\n","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/builder/BaseBuilder.java#L104-L140","documentation":"When a typeHandler alias is resolved from configuration (XML attribute or annotation string), BaseBuilder verifies the resulting class actually implements org.apache.ibatis.type.TypeHandler. A class that resolves fine but is not a TypeHandler implementation fails with this BuilderException.","triggerScenarios":"typeHandler=\"com.example.SomeUtil\" where SomeUtil is a plain utility class; passing a class that only extends a BaseTypeHandler indirectly through generics but was compiled against an incompatible mybatis version (binary incompatibility); specifying a TypeException class or ResultSetHandler where a TypeHandler was expected.","commonSituations":"Copy-pasting the wrong class name into a typeHandler attribute; multiple mybatis jar versions on the classpath so the class implements a different TypeHandler class (different classloader/package); upgrading MyBatis with a custom handler compiled against the old API.","solutions":["Make the referenced class implement/extend TypeHandler/BaseTypeHandler<T>","Eliminate duplicate mybatis jars on the classpath so a single TypeHandler interface is used","Recompile custom handlers against the mybatis version in use"],"exampleFix":"<!-- before -->\n<result column=\"data\" property=\"data\" typeHandler=\"com.example.JsonUtil\"/>\n<!-- after -->\npublic class JsonTypeHandler extends BaseTypeHandler<MyJson> { ... }\n<result column=\"data\" property=\"data\" typeHandler=\"com.example.JsonTypeHandler\"/>","handlingStrategy":"type-guard","validationCode":"Class<?> c = Class.forName(typeHandlerName);\nif (!org.apache.ibatis.type.TypeHandler.class.isAssignableFrom(c)) {\n  throw new IllegalStateException(typeHandlerName + \" is not a TypeHandler\");\n}","typeGuard":"static boolean isTypeHandler(Class<?> c) {\n  return org.apache.ibatis.type.TypeHandler.class.isAssignableFrom(c);\n}","tryCatchPattern":null,"preventionTips":["Extend BaseTypeHandler<T> for custom handlers - it guarantees the interface","Run 'mvn dependency:tree' to eliminate duplicate mybatis versions"],"tags":["mybatis","builder","type-handler","configuration"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}