mybatis/mybatis-3 · error · ExecutorException
Too many keys are generated. There are only %d target object
Error message
Too many keys are generated. There are only %d target objects. You either specified a wrong 'keyProperty' or encountered a driver bug like #1523.
What it means
assignKeysToParamMapList handles batch inserts where the parameter is a list of ParamMap (multi-param or @Param methods). It walks the generated-keys ResultSet and the parameter list in lockstep; if the driver yields more key rows than there are parameter objects, the counts cannot be reconciled. The message points at a wrong keyProperty or a known driver bug (#1523) where drivers return bogus extra generated-key rows.
Source
Thrown at src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java:141
Iterator<?> iterator = params.iterator();
while (rs.next()) {
if (!iterator.hasNext()) {
throw new ExecutorException(
String.format(parameter instanceof Map ? MSG_TOO_MANY_KEYS_FOR_MAP : MSG_TOO_MANY_KEYS, params.size()));
}
Object param = iterator.next();
assignerList.forEach(x -> x.assign(rs, param));
}
}
private void assignKeysToParamMapList(Configuration configuration, ResultSet rs, ResultSetMetaData rsmd,
String[] keyProperties, ArrayList<ParamMap<?>> paramMapList) throws SQLException {
Iterator<ParamMap<?>> iterator = paramMapList.iterator();
List<KeyAssigner> assignerList = new ArrayList<>();
long counter = 0;
while (rs.next()) {
if (!iterator.hasNext()) {
throw new ExecutorException(String.format(MSG_TOO_MANY_KEYS, counter));
}
ParamMap<?> paramMap = iterator.next();
if (assignerList.isEmpty()) {
for (int i = 0; i < keyProperties.length; i++) {
assignerList
.add(getAssignerForParamMap(configuration, rsmd, i + 1, paramMap, keyProperties[i], keyProperties, false)
.getValue());
}
}
assignerList.forEach(x -> x.assign(rs, paramMap));
counter++;
}
}
private void assignKeysToParamMap(Configuration configuration, ResultSet rs, ResultSetMetaData rsmd,
String[] keyProperties, Map<String, ?> paramMap) throws SQLException {
if (paramMap.isEmpty()) {
return;View on GitHub (pinned to 008069adb1)
Solutions
- Upgrade (or roll back) the JDBC driver to a version where getGeneratedKeys() returns exactly one row per inserted row
- Verify keyProperty matches a real writable property on each parameter object
- For batch inserts, set keyProperty with the parameter prefix (e.g. 'items.id') as documented for @Param usage
- If the driver bug cannot be avoided, execute inserts one row per statement or use <selectKey> per row
Defensive patterns
Strategy: try-catch
Try / catch
try { mapper.batchInsert(users); } catch (PersistenceException e) { if (String.valueOf(e.getMessage()).contains("Too many keys")) { log.error("driver key count mismatch — check keyProperty / upgrade JDBC driver (issue #1523)"); } throw e; } Prevention
- Pin the JDBC driver version and regression-test batch inserts after upgrades
- Verify keyProperty names against the parameter classes before shipping
When it happens
Trigger: Batch insert (ExecutorType.BATCH, or multi-row VALUES) with useGeneratedKeys and @Param parameters, using a driver that reports more generated-key rows than inserted rows (bug referenced as issue #1523), or a keyProperty that makes MyBatis misalign the mapping.
Common situations: Upgrading a JDBC driver that changes getGeneratedKeys() behavior for batches; SQL Server / MySQL driver versions returning keys for every batch execution segment.
Related errors
- Too many keys are generated. There are only %d target object
- Error getting generated key or setting result to parameter o
- Could not determine which parameter to assign generated keys
- Could not find parameter '${paramName}'. Note that when ther
- No setter found for the keyProperty '${propertyName}' in '${
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/51dc1eaf8209d3cd.
Report an issue: GitHub.