mybatis/mybatis-3 · error · ReflectionException

Cannot set the value '{}' because the property '{}' is not M

Error message

Cannot set the value '{}' because the property '{}' is not Map, List or Array.

What it means

The set-side counterpart of the unsupported-collection-type read error: BaseWrapper.setCollectionValue only assigns into Map, List and object/primitive arrays. Setting 'prop[i] = value' on any other non-null type (a bean, String, Set, custom collection) throws a ReflectionException because no indexed write semantics exist for that type.

Source

Thrown at src/main/java/org/apache/ibatis/reflection/wrapper/BaseWrapper.java:110

        ((Object[]) collection)[i] = value;
      } else if (collection instanceof char[]) {
        ((char[]) collection)[i] = (Character) value;
      } else if (collection instanceof boolean[]) {
        ((boolean[]) collection)[i] = (Boolean) value;
      } else if (collection instanceof byte[]) {
        ((byte[]) collection)[i] = (Byte) value;
      } else if (collection instanceof double[]) {
        ((double[]) collection)[i] = (Double) value;
      } else if (collection instanceof float[]) {
        ((float[]) collection)[i] = (Float) value;
      } else if (collection instanceof int[]) {
        ((int[]) collection)[i] = (Integer) value;
      } else if (collection instanceof long[]) {
        ((long[]) collection)[i] = (Long) value;
      } else if (collection instanceof short[]) {
        ((short[]) collection)[i] = (Short) value;
      } else {
        throw new ReflectionException("Cannot set the value '" + prop.getIndexedName() + "' because the property '"
            + prop.getName() + "' is not Map, List or Array.");
      }
    }
  }

  protected Object getChildValue(PropertyTokenizer prop) {
    MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
      return null;
    }
    return metaValue.getValue(prop.getChildren());
  }

  protected void setChildValue(PropertyTokenizer prop, Object value) {
    MetaObject metaValue = metaObject.metaObjectForProperty(prop.getIndexedName());
    if (metaValue == SystemMetaObject.NULL_META_OBJECT) {
      if (value == null) {
        // don't instantiate child path if value is null

View on GitHub (pinned to 008069adb1)

Solutions

  1. Use a List, Map, or array as the target type for indexed writes
  2. For Sets, write the whole collection (setValue("tags", setWithNewElement)) or switch the field to List
  3. Update resultMap <collection> mappings when the property type changes to a non-indexable type

Example fix

// before
private Set<String> tags; // setValue("tags[0]", s) throws

// after
private List<String> tags; // setValue("tags[0]", s) works
Defensive patterns

Strategy: type-guard

Validate before calling

Object target = metaObject.getValue("tags");
if (!(target instanceof Map || target instanceof List || target.getClass().isArray())) {
  metaObject.setValue("tags", new java.util.ArrayList<>(/* seed */)); // replace with indexable type
}

Type guard

boolean writableIndexed(Object o) {
  return o instanceof Map || o instanceof List || o.getClass().isArray();
}

Prevention

When it happens

Trigger: MetaObject.setValue("tags[0]", v) where 'tags' is a java.util.Set; result mapping writing indexed elements into a custom collection class; attempting 'str[0] = c' style writes through the reflection wrapper on non-array types.

Common situations: Bean field type changed from List to Set or a custom collection while indexed write paths (resultMaps, generic copiers built on MetaObject) were not updated.

Related errors


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