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
- Fix the property expression so every '[' is closed with ']' before any '.' child separator: 'items[0].name'
- When concatenating indices in dynamic SQL, place the ']' immediately after the index: "items[" + i + "].name"
- Validate/escape user-supplied property paths before passing them to MetaObject
- 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
- Build indexed expressions with a single format template, never string concatenation across the bracket
- Unit-test property-path builders for bracket balance
- Prefer simple dotted paths and let <foreach> handle iteration
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
- Error creating instance. Cause: {cause}
- Parsing error was found in mapping #{{content}}. Check synt
- Error in result map '{resultMapId}'. Failed to find a constr
- Failed to create a new Configuration instance.
- Cannot get Configuration as factory method [" + this.configu
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/3ad40cefe286024e.
Report an issue: GitHub.