{"record":{"id":"ffdca0dae5267622","repo":"mybatis/mybatis-3","slug":"mapping-is-missing-column-attribute-for-property","errorCode":null,"errorMessage":"Mapping is missing column attribute for property {}","messagePattern":"Mapping is missing column attribute for property (.+?)","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/mapping/ResultMapping.java","lineNumber":169,"sourceCode":"\n    public ResultMapping build() {\n      // lock down collections\n      resultMapping.flags = List.copyOf(resultMapping.flags);\n      resultMapping.composites = List.copyOf(resultMapping.composites);\n      validate();\n      return resultMapping;\n    }\n\n    private void validate() {\n      // Issue #697: cannot define both nestedQueryId and nestedResultMapId\n      if (resultMapping.nestedQueryId != null && resultMapping.nestedResultMapId != null) {\n        throw new IllegalStateException(\n            \"Cannot define both nestedQueryId and nestedResultMapId in property \" + resultMapping.property);\n      }\n      // Issue #4 and GH #39: column is optional only in nested resultMaps but not in the rest\n      if (resultMapping.nestedResultMapId == null && resultMapping.column == null\n          && resultMapping.composites.isEmpty()) {\n        throw new IllegalStateException(\"Mapping is missing column attribute for property \" + resultMapping.property);\n      }\n      if (resultMapping.getResultSet() != null) {\n        int numColumns = 0;\n        if (resultMapping.column != null) {\n          numColumns = resultMapping.column.split(\",\").length;\n        }\n        int numForeignColumns = 0;\n        if (resultMapping.foreignColumn != null) {\n          numForeignColumns = resultMapping.foreignColumn.split(\",\").length;\n        }\n        if (numColumns != numForeignColumns) {\n          throw new IllegalStateException(\n              \"There should be the same number of columns and foreignColumns in property \" + resultMapping.property);\n        }\n      }\n    }\n\n    public Builder column(String column) {","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/mapping/ResultMapping.java#L151-L187","documentation":"Thrown by ResultMapping.Builder.validate() when a result mapping has no column, no composite columns, and is not backed by a nested resultMap. MyBatis requires a column for every plain mapping because it is the only way to know which JDBC column feeds the property. Only mappings that select into a nested resultMap (nestedResultMapId set) or use composite columns are exempt.","triggerScenarios":"Building a ResultMapping via new ResultMapping.Builder(configuration, \"prop\", null, javaType).build(), or an XML resultMap entry like <result property=\"prop\" javaType=\"...\"/> with no column attribute and no nested resultMap select.","commonSituations":"Hand-writing a resultMap and forgetting the column attribute; using <id>/<result> elements that only carry javaType; programmatically constructing ResultMapping without calling builder.column(...).","solutions":["Add the column attribute: <result property=\"prop\" column=\"col_name\"/>.","If the value comes from another statement's result map, point at a nested resultMap via resultMap=\"...\" so nestedResultMapId is set.","For multi-column mappings (e.g. composite keys), supply <constructor>/<id> composites or columnPrefix so composites is non-empty.","If building programmatically, call builder.column(\"col_name\") before build()."],"exampleFix":"<!-- before -->\n<result property=\"userName\" javaType=\"string\"/>\n<!-- after -->\n<result property=\"userName\" column=\"user_name\" javaType=\"string\"/>","handlingStrategy":"validation","validationCode":"// before build(): a plain mapping needs a column, composites, or a nested resultMap\nboolean ok = rm.nestedResultMapId != null || rm.column != null || !rm.composites.isEmpty();\n// with the Builder: always call .column(...) for non-nested mappings","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat column as mandatory when writing <result>/<id> entries unless they point at a nested resultMap.","Lint mapper XML (e.g. mybatis-generator or a schema-aware validator) in CI to catch missing attributes."],"tags":["mybatis","resultmap","configuration","mapping"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}