mybatis/mybatis-3 · error · IllegalArgumentException

Invalid index syntax in property: '{}'. Missing closing brac

Error message

Invalid index syntax in property: '{}'. Missing closing bracket.

What it means

PropertyTokenizer parses indexed property paths like 'list[0].name' or 'map[key]'. When a property name (with no remaining children after the last '.') contains '[' but the overall name does not end with ']', the index cannot be extracted, so an IllegalArgumentException is thrown. This is a malformed property-expression error, typically caused by a typo in a mapper XML parameter expression or in MetaObject.getValue/setValue path.

Source

Thrown at src/main/java/org/apache/ibatis/reflection/property/PropertyTokenizer.java:42

  private String name;
  private final String indexedName;
  private String index;
  private final String children;

  public PropertyTokenizer(String fullname) {
    int delim = fullname.indexOf('.');
    if (delim > -1) {
      name = fullname.substring(0, delim);
      children = fullname.substring(delim + 1);
    } else {
      name = fullname;
      children = null;
    }
    indexedName = name;
    delim = name.indexOf('[');
    if (delim > -1) {
      if (children == null && !name.endsWith("]")) {
        throw new IllegalArgumentException(
            "Invalid index syntax in property: '" + name + "'. Missing closing bracket.");
      }
      index = name.substring(delim + 1, name.length() - 1);
      name = name.substring(0, delim);
    }
  }

  public String getName() {
    return name;
  }

  public String getIndex() {
    return index;
  }

  public String getIndexedName() {
    return indexedName;
  }

View on GitHub (pinned to 008069adb1)

Solutions

  1. Fix the property expression so every '[' is closed with ']' before any '.' child separator: 'items[0].name'
  2. When concatenating indices in dynamic SQL, place the ']' immediately after the index: "items[" + i + "].name"
  3. Validate/escape user-supplied property paths before passing them to MetaObject
  4. Log the exact expression string at the call site to spot the malformed segment

Example fix

<!-- before -->
SELECT * FROM t WHERE id = #{items[0}

<!-- after -->
SELECT * FROM t WHERE id = #{items[0].id}
Defensive patterns

Strategy: validation

Validate before calling

boolean validIndexedProperty(String path) {
  for (String seg : path.split("\\.")) {
    int open = seg.indexOf('[');
    if (open > -1 && !seg.endsWith("]")) {
      return false;
    }
  }
  return true;
}
// call before MetaObject.getValue(path)/setValue(path, v)

Try / catch

try {
  metaObject.getValue(path);
} catch (IllegalArgumentException e) {
  if (e.getMessage() != null && e.getMessage().contains("Missing closing bracket")) {
    // reject/repair the property expression; surface to caller as config error
  } else { throw e; }
}

Prevention

When it happens

Trigger: MetaObject.getValue("items[0") or setValue on a path with an unclosed bracket; #{item[0.name} in a mapper (OGNL/parameter path with missing ']'); dynamic SQL concatenation that drops the closing bracket from an index expression like '${list[' + i + '.id]' built incorrectly.

Common situations: Hand-built property expressions in dynamic SQL (<foreach> with index interpolation); typos in resultMap/parameter expressions; string-concatenated index expressions where the ']' lands after a '.' separator instead of before it (e.g. 'a[0.b]' leaves children non-null and index parsing malformed).

Related errors


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