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

  1. Make the keyProperty prefix exactly match the @Param name (or the default param1/arg0 name shown in 'available parameters')
  2. Add the missing @Param annotation so the name exists
  3. 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

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


AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14). Data as JSON: /api/errors/9d77d6779d5f13fb. Report an issue: GitHub.