{"record":{"id":"3b4efa2c36f6bef3","repo":"mybatis/mybatis-3","slug":"could-not-find-type-handler-for-java-type-pro","errorCode":null,"errorMessage":"Could not find type handler for Java type '\" + propertyGenericType.getTypeName() + \"' nor JDBC type '\" + actualJdbcType + \"'","messagePattern":"Could not find type handler for Java type '\" \\+ propertyGenericType\\.getTypeName\\(\\) \\+ \"' nor JDBC type '\" \\+ actualJdbcType \\+ \"'","errorType":"exception","errorClass":"TypeException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/scripting/defaults/DefaultParameterHandler.java","lineNumber":170,"sourceCode":"          }\n          if (value == null) {\n            if (jdbcType == null) {\n              jdbcType = configuration.getJdbcTypeForNull();\n            }\n            if (typeHandler == null) {\n              typeHandler = ObjectTypeHandler.INSTANCE;\n            }\n          } else if (typeHandler == null) {\n            if (propertyGenericType == null) {\n              propertyGenericType = value.getClass();\n            }\n            typeHandler = typeHandlerRegistry.getTypeHandler(propertyGenericType, actualJdbcType, null);\n          }\n          if (typeHandler == null) {\n            typeHandler = typeHandlerRegistry.getTypeHandler(actualJdbcType);\n          }\n          if (typeHandler == null) {\n            throw new TypeException(\"Could not find type handler for Java type '\" + propertyGenericType.getTypeName()\n                + \"' nor JDBC type '\" + actualJdbcType + \"'\");\n          }\n          try {\n            typeHandler.setParameter(ps, i + 1, value, jdbcType);\n          } catch (TypeException | SQLException e) {\n            throw new TypeException(\"Could not set parameters for mapping: \" + parameterMapping + \". Cause: \" + e, e);\n          }\n        }\n      }\n    }\n  }\n\n  private MetaObject getParamMetaObject() {\n    if (paramMetaObject != null) {\n      return paramMetaObject;\n    }\n    paramMetaObject = configuration.newMetaObject(parameterObject);\n    return paramMetaObject;","sourceCodeStart":152,"sourceCodeEnd":188,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/scripting/defaults/DefaultParameterHandler.java#L152-L188","documentation":"DefaultParameterHandler resolves a TypeHandler for each parameter before binding it to the PreparedStatement: first by (Java generic type + JDBC type), then by JDBC type alone, and only as a last resort by Java type. If all lookups fail it throws a TypeException listing the Java type (or the runtime value's class when no generic type was known) and JDBC type — meaning no registered handler can write that combination to the driver.","triggerScenarios":"A parameter whose Java type has no registered handler (custom value objects, exotic JDK types) and no typeHandler specified on the mapping; javaType/jdbcType combination with no handler (e.g. an Enum without default handling in unusual configurations); null javaType on a mapping whose runtime value is a custom class.","commonSituations":"Passing domain objects/adapters as parameters without a TypeHandler; migrating to MyBatis versions where handler registry resolution for generics became stricter; custom JDBC types not covered by BaseTypeHandler registrations.","solutions":["Write a TypeHandler for the parameter type and register it in the config (<typeHandlers> or Configuration.getTypeHandlerRegistry().register(...))","Specify the handler explicitly on the mapping: #{value,typeHandler=com.example.MyTypeHandler}","Pass a supported primitive/wrapper/String representation of the value instead of the custom object","For nulls/odd jdbcTypes, declare javaType and jdbcType on the #{...} placeholder so resolution succeeds"],"exampleFix":"<!-- before -->\n#{body}  <!-- body is a custom JsonValue type -->\n\n<!-- after -->\n#{body,typeHandler=com.example.JsonTypeHandler,jdbcType=VARCHAR}","handlingStrategy":"validation","validationCode":"TypeHandler<?> h = typeHandlerRegistry.getTypeHandler(value != null ? value.getClass() : String.class, jdbcType);\nif (h == null) {\n  // register or specify a handler BEFORE executing the statement\n  throw new IllegalStateException(\"No type handler for \" + value.getClass());\n}","typeGuard":null,"tryCatchPattern":"try {\n  session.selectList(\"stmt\", params);\n} catch (TypeException e) {\n  if (e.getMessage().contains(\"Could not find type handler\")) {\n    // register handler: configuration.getTypeHandlerRegistry().register(MyType.class, new MyHandler()); then retry\n  } else throw e;\n}","preventionTips":["Register TypeHandlers for all custom parameter types at bootstrap","Declare typeHandler (and javaType/jdbcType) on mappings for non-standard types","Add a startup smoke test that executes one statement per custom-typed parameter"],"tags":["type-handler","parameters","jdbc","mybatis"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}