{"record":{"id":"66f452b677c2874e","repo":"mybatis/mybatis-3","slug":"sqlrunner-could-not-find-a-typehandler-instance-fo","errorCode":null,"errorMessage":"SqlRunner could not find a TypeHandler instance for {}","messagePattern":"SqlRunner could not find a TypeHandler instance for (.+?)","errorType":"validation","errorClass":"SQLException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/jdbc/SqlRunner.java","lineNumber":227,"sourceCode":"    try {\n      connection.close();\n    } catch (SQLException e) {\n      // ignore\n    }\n  }\n\n  private void setParameters(PreparedStatement ps, Object... args) throws SQLException {\n    for (int i = 0, n = args.length; i < n; i++) {\n      if (args[i] == null) {\n        throw new SQLException(\n            \"SqlRunner requires an instance of Null to represent typed null values for JDBC compatibility\");\n      }\n      if (args[i] instanceof Null) {\n        ((Null) args[i]).getTypeHandler().setParameter(ps, i + 1, null, ((Null) args[i]).getJdbcType());\n      } else {\n        TypeHandler typeHandler = typeHandlerRegistry.getTypeHandler(args[i].getClass());\n        if (typeHandler == null) {\n          throw new SQLException(\"SqlRunner could not find a TypeHandler instance for \" + args[i].getClass());\n        } else {\n          typeHandler.setParameter(ps, i + 1, args[i], null);\n        }\n      }\n    }\n  }\n\n  private List<Map<String, Object>> getResults(ResultSet rs) throws SQLException {\n    List<Map<String, Object>> list = new ArrayList<>();\n    List<String> columns = new ArrayList<>();\n    List<TypeHandler<?>> typeHandlers = new ArrayList<>();\n    ResultSetMetaData rsmd = rs.getMetaData();\n    for (int i = 0, n = rsmd.getColumnCount(); i < n; i++) {\n      columns.add(rsmd.getColumnLabel(i + 1));\n      try {\n        Class<?> type = Resources.classForName(rsmd.getColumnClassName(i + 1));\n        TypeHandler<?> typeHandler = typeHandlerRegistry.getTypeHandler(type);\n        if (typeHandler == null) {","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/jdbc/SqlRunner.java#L209-L245","documentation":"SqlRunner.setParameters() throws SQLException when TypeHandlerRegistry has no TypeHandler registered for the concrete class of an argument. SqlRunner resolves handlers purely from args[i].getClass(), so any type outside the built-in set (primitives, dates, strings, enums, etc.) and not user-registered fails here.","triggerScenarios":"Passing an exotic argument class to SqlRunner methods: java.util.UUID (older MyBatis versions), java.time Year/Period, a custom value object, or a byte[] subclass, where no handler exists in the registry.","commonSituations":"Using SqlRunner in tests with java.time or custom types not registered; a TypeHandler registered on a Configuration different from the one SqlRunner was constructed with; version upgrades that change default handler coverage.","solutions":["Convert the value to a supported JDBC type before passing it (e.g. uuid.toString(), Year.getValue()).","Register a handler on the Configuration SqlRunner uses: typeHandlerRegistry.register(MyType.class, new MyTypeHandler()) before constructing SqlRunner.","Prefer the normal mapper API (which maps types via parameter xmlType/resultSet metadata) for non-standard types instead of SqlRunner."],"exampleFix":"// before\nrunner.update(\"insert into t(uuid_col) values (?)\", java.util.UUID.randomUUID());\n\n// after\nrunner.update(\"insert into t(uuid_col) values (?)\", java.util.UUID.randomUUID().toString());","handlingStrategy":"validation","validationCode":"// Confirm a handler exists before running\nTypeHandler<?> h = configuration.getTypeHandlerRegistry().getTypeHandler(MyType.class);\nif (h == null) {\n  configuration.getTypeHandlerRegistry().register(MyType.class, new MyTypeHandler());\n}\nSqlRunner runner = new SqlRunner(configuration, conn);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register custom TypeHandlers on the Configuration you hand to SqlRunner before first use.","Convert exotic types (UUID, Year, custom VOs) to String/long/timestamp at the boundary.","Keep a project list of supported argument types for SqlRunner in test utilities."],"tags":["mybatis","type-handler","jdbc","sql-runner"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}