{"record":{"id":"2e310953c94793af","repo":"mybatis/mybatis-3","slug":"resultmaps-must-have-an-id","errorCode":null,"errorMessage":"ResultMaps must have an id","messagePattern":"ResultMaps must have an id","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/mapping/ResultMap.java","lineNumber":91,"sourceCode":"      resultMap.configuration = configuration;\n      resultMap.id = id;\n      resultMap.type = type;\n      resultMap.resultMappings = resultMappings;\n      resultMap.autoMapping = autoMapping;\n    }\n\n    public Builder discriminator(Discriminator discriminator) {\n      resultMap.discriminator = discriminator;\n      return this;\n    }\n\n    public Class<?> type() {\n      return resultMap.type;\n    }\n\n    public ResultMap build() {\n      if (resultMap.id == null) {\n        throw new IllegalArgumentException(\"ResultMaps must have an id\");\n      }\n\n      resultMap.mappedColumns = new HashSet<>();\n      resultMap.mappedProperties = new HashSet<>();\n      resultMap.idResultMappings = new ArrayList<>();\n      resultMap.constructorResultMappings = new ArrayList<>();\n      resultMap.propertyResultMappings = new ArrayList<>();\n\n      for (ResultMapping resultMapping : resultMap.resultMappings) {\n        resultMap.hasNestedQueries = resultMap.hasNestedQueries || resultMapping.getNestedQueryId() != null;\n        resultMap.hasNestedResultMaps = resultMap.hasNestedResultMaps || resultMapping.getNestedResultMapId() != null\n            && resultMapping.getResultSet() == null && !JdbcType.CURSOR.equals(resultMapping.getJdbcType());\n        final String column = resultMapping.getColumn();\n        if (column != null) {\n          resultMap.mappedColumns.add(column.toUpperCase(Locale.ENGLISH));\n        } else if (resultMapping.isCompositeResult()) {\n          for (ResultMapping compositeResultMapping : resultMapping.getComposites()) {\n            final String compositeColumn = compositeResultMapping.getColumn();","sourceCodeStart":73,"sourceCodeEnd":109,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/mapping/ResultMap.java#L73-L109","documentation":"ResultMap.Builder.build() throws IllegalArgumentException when the resultMap being constructed has a null id. Every ResultMap must be identifiable (usually its namespace-qualified name) because statements, nested mappings and Discriminators reference result maps by id.","triggerScenarios":"Programmatically building ResultMap without new ResultMap.Builder(configuration, null).with... — i.e. passing a null id; XML <resultMap> always generates an id, so this is almost exclusive to Java-built configurations and custom language drivers.","commonSituations":"Constructing ResultMaps dynamically (e.g. for dynamic schemas in generic frameworks) and forgetting to generate a unique id; utility code that copies ResultMaps but drops the id; third-party plugins built against older APIs.","solutions":["Pass a non-null, unique id: new ResultMap.Builder(config, \"com.example.UserResult\", User.class, mappings).build().","When generating dynamically, derive the id from class + mapping hash to keep it stable and unique.","Register the built ResultMap under the same id in Configuration.addResultMap so references resolve."],"exampleFix":"// before\nResultMap rm = new ResultMap.Builder(config, null, User.class, mappings).build();\n\n// after\nResultMap rm = new ResultMap.Builder(config, \"com.example.mapper.UserMapper.UserResult\", User.class, mappings).build();","handlingStrategy":"validation","validationCode":"// Generate a stable unique id when building ResultMaps dynamically\nString id = User.class.getName() + \"#\" + Integer.toHexString(mappings.hashCode());\nResultMap rm = new ResultMap.Builder(config, id, User.class, mappings).build();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass null as the ResultMap id; derive it from the mapped type plus a discriminator.","Register built ResultMaps via configuration.addResultMap(rm) under the same id so references resolve.","Prefer XML <resultMap> where ids are generated automatically, unless dynamic mapping is required."],"tags":["mybatis","result-map","configuration","null-check"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}