mybatis/mybatis-3 · error · BuilderException
Parsing error was found in mapping #{{content}}. Check synt
Error message
Parsing error was found in mapping #{{content}}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} What it means
A generic wrapper in ParameterMappingTokenHandler.parseParameterMapping(): new ParameterExpression(content) threw something other than a BuilderException (e.g. StringIndexOutOfBoundsException from malformed input), which is rethrown as a BuilderException with a hint showing the expected #{property,(expression),var1=value1,...} syntax and the original exception as cause.
Source
Thrown at src/main/java/org/apache/ibatis/builder/ParameterMappingTokenHandler.java:192
if (Map.class.isAssignableFrom(parameterType)) {
return Object.class;
}
MetaClass metaClass = MetaClass.forClass(parameterType, configuration.getReflectorFactory());
if (metaClass.hasGetter(property)) {
Entry<Type, Class<?>> getterType = metaClass.getGenericGetterType(property);
genericType = getterType.getKey();
return getterType.getValue();
}
return Object.class;
}
private Map<String, String> parseParameterMapping(String content) {
try {
return new ParameterExpression(content);
} catch (BuilderException ex) {
throw ex;
} catch (Exception ex) {
throw new BuilderException("Parsing error was found in mapping #{" + content
+ "}. Check syntax #{property|(expression), var1=value1, var2=value2, ...} ", ex);
}
}
}
View on GitHub (pinned to 008069adb1)
Solutions
- Inspect the exact content shown in the message and fix the placeholder to #{property} or #{property,opt=val}
- If SQL is generated, add a unit test asserting generated placeholders match /#\{[^}]+}/ and never emit empty or leading-comma placeholders
- Log the cause exception — its stack trace pinpoints the parse step that choked
Example fix
-- before (generated SQL fragment)
WHERE id = #{}
-- after
WHERE id = #{id} Defensive patterns
Strategy: try-catch
Validate before calling
// Sanity-check generated SQL placeholders before creating the statement
for (String ph : extractPlaceholders(sql)) { // regex /#\{([^}]*)\}/
if (ph.isBlank() || ph.startsWith(",") || ph.endsWith(",") || ph.contains("=,") || ph.contains("=}")) {
throw new IllegalArgumentException("Malformed placeholder #{" + ph + "} in generated SQL");
}
} Try / catch
try {
configuration.addMappedStatement(...);
} catch (BuilderException e) {
Throwable cause = e.getCause();
log.error("Placeholder parse failed for: {} (cause: {})", content, cause);
throw e; // configuration errors must not be swallowed
} Prevention
- Never build #{} placeholders by string concatenation of user input — pass bound parameters instead
- Template-generated SQL should round-trip through a placeholder validator in unit tests
When it happens
Trigger: Severely malformed placeholders such as #{}, #{,}, #{a,b=} that crash the low-level parser instead of producing a clean BuilderException; unbalanced separators or empty segments.
Common situations: Programmatically generated SQL concatenating user input into #{} placeholders; template engines (FreeMarker/Velocity) emitting broken placeholder text; edge-case inputs the hand-written recursive-descent parser does not guard.
Related errors
- Parsing error in {{expression}} in position {p}
- An invalid property '{name}' was found in mapping #{{content
- Invalid index syntax in property: '{}'. Missing closing brac
- Dynamic content is not allowed when using RAW language
- The expression '" + expression + "' evaluated to a null valu
AI-assisted analysis of mybatis/mybatis-3@008069adb1 (2026-08-14).
Data as JSON: /api/errors/5b0b3ed1db7d8def.
Report an issue: GitHub.