{"record":{"id":"ec82747b9c073e57","repo":"baomidou/mybatis-plus","slug":"failed-invoking-constructor-for-handler","errorCode":null,"errorMessage":"Failed invoking constructor for handler {}","messagePattern":"Failed invoking constructor for handler (.+?)","errorType":"exception","errorClass":"TypeException","httpStatus":null,"severity":"error","filePath":"mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java","lineNumber":97,"sourceCode":"     * @param javaTypeClass java类型信息\n     * @param field         属性字段\n     * @return 实例化类型处理器\n     */\n    public static TypeHandler<?> newJsonTypeHandler(Class<? extends TypeHandler<?>> typeHandler, Class<?> javaTypeClass, Field field) {\n        TypeHandler<?> result = null;\n        if (IJsonTypeHandler.class.isAssignableFrom(typeHandler)) {\n            if (field != null) {\n                try {\n                    result = typeHandler.getConstructor(Class.class, Field.class).newInstance(javaTypeClass, field);\n                } catch (ReflectiveOperationException e) {\n                    // ignore\n                }\n            }\n            if (result == null) {\n                try {\n                    result = typeHandler.getConstructor(Class.class).newInstance(javaTypeClass);\n                } catch (ReflectiveOperationException ex) {\n                    throw new TypeException(\"Failed invoking constructor for handler \" + typeHandler, ex);\n                }\n            }\n        }\n        return result;\n    }\n\n    /**\n     * 获取SqlSessionFactory\n     * <p>当自定义实现{@link SqlSession}时,请实现对{@link SqlSessionFactory}的访问 (spring的方式)</p>\n     * <p>当无法获得{@link SqlSessionFactory}时,需要将{@link SqlSessionFactory}绑定至上下文对象中(原生mybatis访问方式)</p>\n     *\n     * @param mybatisMapperProxy {@link MybatisMapperProxy}\n     * @return SqlSessionFactory\n     * @see DefaultSqlSession\n     * @see GlobalConfigUtils#getGlobalConfig(Configuration)\n     * @see GlobalConfigUtils#setGlobalConfig(Configuration, GlobalConfig)\n     * @since 3.5.7\n     */","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/baomidou/mybatis-plus/blob/bf67d907478c724120bf76292da54abf9e73c2b3/mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/MybatisUtils.java#L79-L115","documentation":"MybatisUtils' type-handler factory instantiates an IJsonTypeHandler. It first tries the constructor (Class, Field); if no Field is available it falls back to the (Class) constructor. If that reflective instantiation throws (wrong constructor signature, abstract class, inaccessible constructor, or constructor itself failing), it is wrapped in a MyBatis TypeException: 'Failed invoking constructor for handler <type>'.","triggerScenarios":"Configuring a custom type handler implementing IJsonTypeHandler whose only constructors do not match (Class, Field) or (Class) — e.g. one that takes only a Field, takes (Class, String), or has only a no-arg constructor with a non-public modifier. It also fires when the matched constructor exists but throws (missing JSON library on classpath, null javaType).","commonSituations":"Upgrading mybatis-plus versions where the expected handler constructor shape changed; writing a Jackson/Fastjson type handler with a non-standard constructor; deploying a custom handler whose constructor calls a dependency that is not wired.","solutions":["Give the handler a public constructor accepting (Class javaType) and, for field-level instantiation, public (Class javaType, Field field).","Ensure the class is concrete (not abstract/interface) and the constructors are public.","If the constructor body throws, check its cause chain (ex) — commonly a missing JSON dependency (jackson-databank / fastjson) that must be added to the classpath.","Verify the javaType class passed in is loadable and non-null in the type handler registration."],"exampleFix":"// before: incompatible constructor -> TypeException\npublic class JsonTypeHandler extends BaseTypeHandler<MyBean> {\n    public JsonTypeHandler(Field field) { ... }\n}\n\n// after: provide the expected (Class) constructor (and optionally (Class, Field))\npublic class JsonTypeHandler extends BaseTypeHandler<MyBean> {\n    public JsonTypeHandler(Class<?> type) {\n        super();\n        this.type = Objects.requireNonNull(type);\n    }\n    public JsonTypeHandler(Class<?> type, Field field) {\n        this(type);\n        this.field = field;\n    }\n}","handlingStrategy":"validation","validationCode":"Class<? extends TypeHandler<?>> h = MyHandler.class;\nboolean hasClassCtor = false;\nfor (Constructor<?> c : h.getConstructors()) {\n    Class<?>[] p = c.getParameterTypes();\n    if (p.length == 1 && p[0] == Class.class) hasClassCtor = true;\n}\nif (!hasClassCtor) throw new IllegalStateException(h + \" needs a public (Class) constructor\");","typeGuard":"static boolean isInstantiableJsonHandler(Class<?> t) {\n    return IJsonTypeHandler.class.isAssignableFrom(t)\n        && !t.isInterface() && !java.lang.reflect.Modifier.isAbstract(t.getModifiers());\n}","tryCatchPattern":"try {\n    TypeHandler<?> th = newGeneratorInstance(handlerClass, javaType);\n} catch (TypeException e) {\n    throw new IllegalStateException(\"Handler \" + handlerClass.getName()\n        + \" must expose public (Class[, Field]) constructors; root cause: \" + e.getCause(), e);\n}","preventionTips":["Standardize custom JSON handlers on public (Class javaType) and (Class, Field) constructors.","Add a startup smoke test that instantiates each registered handler once."],"tags":["type-handler","reflection","json","configuration"],"backgroundTag":null,"analyzedSha":"bf67d907478c724120bf76292da54abf9e73c2b3","analyzedAt":"2026-08-14T15:17:09.543Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}