mybatis/mybatis-3 · error · ExecutorException
Could not find parameter '${paramName}'. Note that when ther
Error message
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 ${keyProperties} and available parameters are ${keySet} What it means
When keyProperty contains a parameter prefix (e.g. 'user.id'), MyBatis splits it at the first dot and looks up 'user' among the available parameter names. If that name is not in the ParamMap and there is more than one parameter, the target parameter simply does not exist, so this ExecutorException (echoing the missing name, the specified keyProperties, and the available parameters) is thrown.
Source
Thrown at src/main/java/org/apache/ibatis/executor/keygen/Jdbc3KeyGenerator.java:207
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);
}
}
private Entry<String, KeyAssigner> getAssignerForSingleParam(Configuration config, ResultSetMetaData rsmd,
int columnPosition, Map<String, ?> paramMap, String keyProperty, boolean omitParamName) {
// Assume 'keyProperty' to be a property of the single param.
String singleParamName = nameOfSingleParam(paramMap);
String argParamName = omitParamName ? null : singleParamName;
return Map.entry(singleParamName, new KeyAssigner(config, rsmd, columnPosition, argParamName, keyProperty));
}
private static String nameOfSingleParam(Map<String, ?> paramMap) {
// There is virtually one parameter, so any key works.
return paramMap.keySet().iterator().next();
}View on GitHub (pinned to 008069adb1)
Solutions
- Make the keyProperty prefix exactly match the @Param name (or the default param1/arg0 name shown in 'available parameters')
- Add the missing @Param annotation so the name exists
- Copy the correct name from the error message's 'available parameters are [...]' list
Example fix
<!-- before: @Param("user") but keyProperty uses 'item' -->
<insert ... keyProperty="item.id">
<!-- after -->
<insert ... keyProperty="user.id"> Defensive patterns
Strategy: validation
Validate before calling
// Verify the prefix matches a declared @Param before first use
String prefix = keyProperty.split("\\.")[0];
boolean ok = Arrays.stream(method.getParameters()).anyMatch(p -> p.isAnnotationPresent(Param.class) && p.getAnnotation(Param.class).value().equals(prefix));
if (!ok) throw new IllegalStateException("keyProperty prefix '" + prefix + "' matches no @Param"); Prevention
- The error message lists available parameter names — copy the name from it verbatim
- Rename @Param and keyProperty in the same commit
When it happens
Trigger: keyProperty="item.id" when the @Param is named differently (e.g. @Param("user") or no annotation so MyBatis used arg0/param1); renaming a @Param annotation without updating keyProperty; typos in the prefix.
Common situations: Refactoring parameter names, mixing positional names (arg0, param1) with custom @Param names, copying an XML statement from another mapper with different parameter names.
Related errors
- Could not determine which parameter to assign generated keys
- 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/9d77d6779d5f13fb.
Report an issue: GitHub.