Tencent/APIJSON · error · UnsupportedOperationException
字符串 ${expression} 不合法!预编译模式下 @having:"column?value;function(
Error message
字符串 ${expression} 不合法!预编译模式下 @having:"column?value;function(arg0,arg1,...)?value..." 中 column?value 必须符合正则表达式 ${PATTERN_FUNCTION} 且不包含连续减号 -- !不允许空格! What it means
In prepared mode, a @having expression without parentheses must fully match PATTERN_FUNCTION (the column?value form). No spaces, no consecutive dashes --, only the whitelisted operator/comparison shape. This is the primary injection guard for HAVING since values cannot be bound parameters inside expressions.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:1768
protected String gainHavingItem(String quote, String table, String alias
, String key, String expression, boolean containRaw) throws Exception {
//fun(arg0,arg1,...)
if (containRaw) {
String rawSQL = gainRawSQL(KEY_HAVING, expression);
if (rawSQL != null) {
return rawSQL;
}
}
if (expression.length() > 100) {
throw new UnsupportedOperationException("@having:value 的 value 中字符串 " + expression + " 不合法!"
+ "不允许传超过 100 个字符的函数或表达式!请用 @raw 简化传参!");
}
int start = expression.indexOf("(");
if (start < 0) {
if (isPrepared() && PATTERN_FUNCTION.matcher(expression).matches() == false) {
throw new UnsupportedOperationException("字符串 " + expression + " 不合法!"
+ "预编译模式下 @having:\"column?value;function(arg0,arg1,...)?value...\""
+ " 中 column?value 必须符合正则表达式 " + PATTERN_FUNCTION + " 且不包含连续减号 -- !不允许空格!");
}
return parseSQLExpression(KEY_HAVING, expression, containRaw, false, null);
}
int end = expression.lastIndexOf(")");
if (start >= end) {
throw new IllegalArgumentException("字符 " + expression + " 不合法!"
+ "@having:value 中 value 里的 SQL函数必须为 function(arg0,arg1,...) 这种格式!");
}
String method = expression.substring(0, start);
if (method.isEmpty() == false) {
if (SQL_FUNCTION_MAP == null || SQL_FUNCTION_MAP.isEmpty()) {
if (StringUtil.isName(method) == false) {
throw new IllegalArgumentException("字符 " + method + " 不合法!"View on GitHub (pinned to 5284052872)
Solutions
- Remove all spaces: "@having": "amount>0"
- Use the supported key(condition) form and APIJSON operators instead of raw SQL keywords
- For legitimately complex expressions use @raw + server-side RAW_MAP
Example fix
// before
{"@having": "amount > 0"}
// after
{"@having": "amount>0"} Defensive patterns
Strategy: validation
Validate before calling
// mirror of the server check for the no-paren form: no spaces, no '--'
const okSimple = s => /^[A-Za-z0-9_.]+(>=|<=|>|<|!=|=)[^\s'\-]*$/.test(s) && !s.includes('--');
const hv = obj['@having'];
if (typeof hv === 'string' && !hv.includes('(') && !okSimple(hv)) {
throw new Error(`@having '${hv}' fails column?value pattern (no spaces, no --)`);
} Type guard
const isSimpleHavingValid = s => typeof s === 'string' && !/\s/.test(s) && !s.includes('--'); Try / catch
try { await api.get(req); } catch (e) { if (e.message.includes('PATTERN_FUNCTION')) req['User']['@having'] = req['User']['@having'].replace(/\s+/g, ''); else throw e; } Prevention
- Never minify by trimming spaces client-side only after an error — build clean strings from the start
- Forbid spaces in @having at the input layer
When it happens
Trigger: "@having": "amount > 0" (spaces), "@having": "a--b>1" (double dash), "@having": "name='x' or 1=1" — any parentheses-free expression that fails the regex.
Common situations: Pretty-printed JSON with spaces inside the value; frontend template inserting user text unescaped; trying SQL syntax (OR, quotes) that the pattern intentionally forbids.
Related errors
- {}: { @key(): value } 对应存储过程 value 中字符 {} 不合法!schema.functio
- @group:value 中 value里面用 , 分割的每一项都必须是1个单词!并且不要有空格!
- @having:value 的 value 中字符串 ${expression} 不合法!不允许传超过 100 个字符的
- 字符 ${expression} 不合法!@having:value 中 value 里的 SQL函数必须为 funct
- 字符 ${method} 不合法!预编译模式下 @having:"column?value;function(arg0,
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/0ae849e6d03aa1f7.
Report an issue: GitHub.