{"record":{"id":"e7b75f26d1323f3b","repo":"mybatis/mybatis-3","slug":"statement-returned-more-than-one-row-where-no-mor","errorCode":null,"errorMessage":"Statement returned more than one row, where no more than one was expected.","messagePattern":"Statement returned more than one row, where no more than one was expected\\.","errorType":"exception","errorClass":"ExecutorException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/apache/ibatis/executor/ResultExtractor.java","lineNumber":57,"sourceCode":"    if (targetType != null && targetType.isAssignableFrom(list.getClass())) {\n      value = list;\n    } else if (targetType != null && objectFactory.isCollection(targetType)) {\n      value = objectFactory.create(targetType);\n      MetaObject metaObject = configuration.newMetaObject(value);\n      metaObject.addAll(list);\n    } else if (targetType != null && targetType.isArray()) {\n      Class<?> arrayComponentType = targetType.getComponentType();\n      Object array = Array.newInstance(arrayComponentType, list.size());\n      if (arrayComponentType.isPrimitive()) {\n        for (int i = 0; i < list.size(); i++) {\n          Array.set(array, i, list.get(i));\n        }\n        value = array;\n      } else {\n        value = list.toArray((Object[]) array);\n      }\n    } else if (list != null && list.size() > 1) {\n      throw new ExecutorException(\"Statement returned more than one row, where no more than one was expected.\");\n    } else if (list != null && list.size() == 1) {\n      value = list.get(0);\n    }\n    return value;\n  }\n}\n","sourceCodeStart":39,"sourceCodeEnd":64,"githubUrl":"https://github.com/mybatis/mybatis-3/blob/008069adb1b089579b5dcba87ee591908b263274/src/main/java/org/apache/ibatis/executor/ResultExtractor.java#L39-L64","documentation":"ResultExtractor converts a query's result list into the method's declared return type. When the target type is neither a Collection nor an array but the JDBC result set produced more than one row, there is no valid way to squeeze multiple rows into a single-object return, so an ExecutorException is thrown. This is the internal machinery behind SqlSession.selectOne()'s 'returned more than one result' behavior for mapped statements with scalar/single-object result types.","triggerScenarios":"Calling a mapper method whose return type is a single object (e.g. User selectById(...)) whose SQL matches more than one row; using selectOne semantics on a statement whose ResultMap maps to a non-collection type while the query returns 2+ rows.","commonSituations":"A WHERE clause that was assumed unique (bad data, missing unique constraint), missing LIMIT 1 / FETCH FIRST 1 ROWS ONLY, date-range queries that accidentally match duplicates, or a join that fans out rows.","solutions":["Fix the query so it returns at most one row: tighten the WHERE clause or add LIMIT 1 / FETCH FIRST 1 ROWS ONLY","Add a unique constraint on the queried column(s) if uniqueness is the intent","If multiple rows are legitimately possible, change the mapper return type to List<T> or an array type"],"exampleFix":"// before\nUser selectByEmail(String email); // two users share the email -> exception\n\n// after\nList<User> selectByEmail(String email); // or ensure email is unique in DB","handlingStrategy":"validation","validationCode":"// If more than one row is possible, query the collection and pick safely\nList<User> rows = sqlSession.selectList(\"selectByEmail\", email);\nif (rows.size() > 1) { throw new IllegalStateException(\"email not unique: \" + rows.size()); }\nUser u = rows.isEmpty() ? null : rows.get(0);","typeGuard":null,"tryCatchPattern":"try { mapper.selectById(id); } catch (PersistenceException e) { if (e.getMessage() != null && e.getMessage().contains(\"more than one row\")) { /* dedupe data or switch to selectList */ } else throw e; }","preventionTips":["Add unique constraints for columns used in single-row lookups","Prefer selectList + explicit pick when uniqueness is not guaranteed by the schema"],"tags":["result-mapping","select-one","sql"],"backgroundTag":null,"analyzedSha":"008069adb1b089579b5dcba87ee591908b263274","analyzedAt":"2026-08-14T13:07:10.264Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}