mybatis/mybatis-3 · error · ExecutorException
Could not determine which parameter to assign generated keys
Error message
Could not determine which parameter to assign generated keys to. Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). Specified key properties are ${keyProperties} and available parameters are ${keySet} What it means
getAssignerForParamMap decides which parameter object receives each generated key. When a mapper method has multiple parameters (the ParamMap contains more than one name), MyBatis cannot guess which parameter a bare keyProperty like 'id' belongs to, so it requires the parameter name to be embedded in the keyProperty (e.g. 'item.id'). Without the prefix, this ExecutorException listing the specified keyProperties and available parameter names is thrown.
Source
Thrown at src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java:193
Object param = pair.getKey().next();
pair.getValue().forEach(x -> x.assign(rs, param));
}
counter++;
}
}
private Entry<String, KeyAssigner> getAssignerForParamMap(Configuration config, ResultSetMetaData rsmd,
int columnPosition, Map<String, ?> paramMap, String keyProperty, String[] keyProperties, boolean omitParamName) {
Set<String> keySet = paramMap.keySet();
// A caveat : if the only parameter has {@code @Param("param2")} on it,
// it must be referenced with param name e.g. 'param2.x'.
boolean singleParam = !keySet.contains(SECOND_GENERIC_PARAM_NAME);
int firstDot = keyProperty.indexOf('.');
if (firstDot == -1) {
if (singleParam) {
return getAssignerForSingleParam(config, rsmd, columnPosition, paramMap, keyProperty, omitParamName);
}
throw new ExecutorException("Could not determine which parameter to assign generated keys to. "
+ "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
+ "Specified key properties are " + ArrayUtil.toString(keyProperties) + " and available parameters are "
+ keySet);
}
String paramName = keyProperty.substring(0, firstDot);
if (keySet.contains(paramName)) {
String argParamName = omitParamName ? null : paramName;
String argKeyProperty = keyProperty.substring(firstDot + 1);
return Map.entry(paramName, new KeyAssigner(config, rsmd, columnPosition, argParamName, argKeyProperty));
}
if (singleParam) {
return getAssignerForSingleParam(config, rsmd, columnPosition, paramMap, keyProperty, omitParamName);
} else {
throw new ExecutorException("Could not find parameter '" + paramName + "'. "
+ "Note that when there are multiple parameters, 'keyProperty' must include the parameter name (e.g. 'param.id'). "
+ "Specified key properties are " + ArrayUtil.toString(keyProperties) + " and available parameters are "
+ keySet);
}View on GitHub (pinned to 008069adb1)
Solutions
- Prefix keyProperty with the parameter name: keyProperty="user.id" (or the @Param name)
- Keep the insert method single-parameter so a bare keyProperty is unambiguous
- Verify the parameter name matches the @Param annotation or the mapped key shown in the error's 'available parameters' list
Example fix
<!-- before -->
int insert(@Param("user") User user, @Param("flag") int flag);
<insert ... keyProperty="id">
<!-- after -->
<insert ... keyProperty="user.id"> Defensive patterns
Strategy: validation
Validate before calling
// Convention check in a shared base mapper or code review rule:
// any insert method with >1 parameter must use keyProperty="<paramName>.<prop>"
int paramCount = method.getParameters().length;
if (paramCount > 1 && !keyProperty.contains(".")) throw new IllegalStateException("keyProperty must be prefixed with the parameter name"); Prevention
- When adding a parameter to an insert method, immediately prefix keyProperty with the @Param name
- Add a startup assertion/test that every multi-param insert's keyProperty contains a dot
When it happens
Trigger: Mapper method with two or more parameters (with or without @Param) combined with useGeneratedKeys="true" and a keyProperty that has no dot, e.g. keyProperty="id" instead of keyProperty="user.id".
Common situations: Adding an extra parameter (e.g. a flag or a second entity) to an existing single-param insert method and forgetting to prefix keyProperty; using Map<String,Object> with multiple entries as sole parameter.
Related errors
- Could not find parameter '${paramName}'. Note that when ther
- Error getting generated key or setting result to parameter o
- Too many keys are generated. There are only %d target object
- Too many keys are generated. There are only %d target object
- No setter found for the keyProperty '${propertyName}' in '${
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/2f2c270e3806116c.
Report an issue: GitHub.