{"record":{"id":"6ec664f8ac7fc07a","repo":"mybatis/mybatis-3","slug":"constructor-auto-mapping-of-1-failed-because","errorCode":null,"errorMessage":"Constructor auto-mapping of ''{1}'' failed because ''{0}'' were not found in the result set; Available columns are ''{2}'' and mapUnderscoreToCamelCase is ''{3}''.","messagePattern":"Constructor auto-mapping of ''(.+?)'' failed because ''(.+?)'' were not found in the result set; Available columns are ''(.+?)'' and mapUnderscoreToCamelCase is ''(.+?)''\\.","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java","lineNumber":964,"sourceCode":"          constructorArgTypes.add(paramType);\n          constructorArgs.add(value);\n          final String mapKey = resultMap.getId() + \":\" + columnPrefix;\n          if (!autoMappingsCache.containsKey(mapKey)) {\n            constructorAutoMappingColumns.computeIfAbsent(mapKey, k -> new ArrayList<>()).add(columnName);\n          }\n          columnNotFound = false;\n          foundValues = value != null || foundValues;\n        }\n      }\n      if (columnNotFound) {\n        if (missingArgs == null) {\n          missingArgs = new ArrayList<>();\n        }\n        missingArgs.add(paramName);\n      }\n    }\n    if (foundValues && constructorArgs.size() < params.length) {\n      throw new ExecutorException(MessageFormat.format(\n          \"Constructor auto-mapping of ''{1}'' failed \" + \"because ''{0}'' were not found in the result set; \"\n              + \"Available columns are ''{2}'' and mapUnderscoreToCamelCase is ''{3}''.\",\n          missingArgs, constructor, rsw.getColumnNames(), configuration.isMapUnderscoreToCamelCase()));\n    }\n    return foundValues;\n  }\n\n  private boolean columnMatchesParam(String columnName, String paramName, String columnPrefix) {\n    if (columnPrefix != null) {\n      if (!columnName.toUpperCase(Locale.ENGLISH).startsWith(columnPrefix)) {\n        return false;\n      }\n      columnName = columnName.substring(columnPrefix.length());\n    }\n    return paramName\n        .equalsIgnoreCase(configuration.isMapUnderscoreToCamelCase() ? columnName.replace(\"_\", \"\") : columnName);\n  }\n","sourceCodeStart":946,"sourceCodeEnd":982,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/resultset/DefaultResultSetHandler.java#L946-L982","documentation":"Thrown during argument-name-based constructor auto-mapping when at least one column matched and produced a value, but some constructor parameters had no matching column in the result set. The message lists the missing parameter names, the available column names, and the current mapUnderscoreToCamelCase setting, since a name/case/underscore mismatch is the usual cause.","triggerScenarios":"argNameBasedConstructorAutoMapping enabled, class compiled with -parameters (or explicit param names), query executed, and a constructor parameter name (after optional underscore-to-camel translation and column prefix stripping via columnMatchesParam) matches no column in rsw.getColumnNames(). Only thrown when foundValues is true, i.e. partial matching succeeded.","commonSituations":"DB columns use snake_case (user_name) but mapUnderscoreToCamelCase is false and the parameter is userName; column aliases renamed in SQL; SELECT omits one column the constructor declares; parameter renamed in a refactor while the SQL stayed; joined/prefixed result maps where the prefix does not match.","solutions":["Alias the SQL columns to match constructor parameter names exactly: SELECT user_name AS userName.","Enable mapUnderscoreToCamelCase (<setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>) if columns are snake_case and parameters camelCase.","Add the missing column(s) to the SELECT list, or remove/rename the constructor parameter to an existing column.","Verify the code was compiled with -parameters so parameter names are the real names, not arg0/arg1."],"exampleFix":"// before\n// mybatis-config.xml: mapUnderscoreToCamelCase=false\n// SELECT id, user_name FROM users\npublic User(Long id, String userName) { ... } // 'userName' not found\n\n// after\n// mybatis-config.xml: <setting name=\"mapUnderscoreToCamelCase\" value=\"true\"/>\n// SELECT id, user_name FROM users\npublic User(Long id, String userName) { ... }","handlingStrategy":"validation","validationCode":"// after compiling with -parameters, assert every ctor param has a matching column\nList<String> cols = ...; // from ResultSetMetaData.getColumnLabels, upper-cased\nboolean camel = configuration.isMapUnderscoreToCamelCase();\nfor (Parameter p : ctor.getParameters()) {\n  String expected = camel\n      ? Arrays.stream(p.getName().split(\"(?=[A-Z])\")).map(String::toLowerCase).collect(joining(\"_\"))\n      : p.getName();\n  if (!cols.contains(expected.toUpperCase(Locale.ENGLISH))) {\n    throw new IllegalStateException(\"No column for constructor param '\" + p.getName() + \"'; columns: \" + cols);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compile with -parameters and keep parameter names equal to column names modulo camelCase.","Turn mapUnderscoreToCamelCase on project-wide for snake_case schemas instead of per-column aliasing.","Cover each constructor-mapped query with a test that asserts all fields are populated (a null field hints at partial matching before it becomes an exception)."],"tags":["mybatis","constructor-automapping","column-mapping","naming"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}