Tencent/APIJSON · error · IllegalArgumentException
字符 ${expression} 不合法!@having:value 中 value 里的 SQL函数必须为 funct
Error message
字符 ${expression} 不合法!@having:value 中 value 里的 SQL函数必须为 function(arg0,arg1,...) 这种格式! What it means
The @having expression contains '(' but the last ')' is at or before the first '(' — the parser cannot extract a function(arg0,arg1,...) call, so it throws. Every SQL function used in @having must be written as name(args) with the closing paren after the opening one.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:1778
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 + " 不合法!"
+ "预编译模式下 @having:\"column?value;function(arg0,arg1,...)?value...\""
+ " 中 function 必须符合小写英文单词的 SQL 函数名格式!");
}
}
else if (SQL_FUNCTION_MAP.containsKey(method) == false) {
throw new IllegalArgumentException("字符 " + method + " 不合法!"
+ "预编译模式下 @column:\"column0,column1:alias;function0(arg0,arg1,...);function1(...):alias...\""
+ " 中 function 必须符合小写英文单词的 SQL 函数名格式!且必须是后端允许调用的 SQL 函数!");
}
}View on GitHub (pinned to 5284052872)
Solutions
- Write complete function calls: "@having": "max(amount)>100"
- Validate balanced parentheses client-side before sending
- Check that JSON string escaping did not eat a closing paren
Example fix
// before
{"@having": "sum(amount>1000"}
// after
{"@having": "sum(amount)>1000"} Defensive patterns
Strategy: validation
Validate before calling
const hv = obj['@having'];
if (typeof hv === 'string' && hv.includes('(')) {
const open = hv.indexOf('('), close = hv.lastIndexOf(')');
if (open >= close) throw new Error(`@having '${hv}' must be function(arg0,...) with ')' after '('`);
} Type guard
const hasBalancedFuncSyntax = s => typeof s === 'string' && (!s.includes('(') || s.indexOf('(') < s.lastIndexOf(')')); Try / catch
try { await api.get(req); } catch (e) { if (e.message.includes('function(arg0,arg1,...)')) highlightBrokenExpression(e.message); else throw e; } Prevention
- Assemble function expressions from tested fragments, not string slicing
- Run a paren-balance lint on generated @having values
When it happens
Trigger: "@having": "max(" , "@having": "sum(1,2" , or "@having": ")sum(" — malformed or truncated function syntax where indexOf('(') >= lastIndexOf(')').
Common situations: String concatenation cuts off the tail of the expression; user typos; templating that drops the closing parenthesis; nested quotes swallowing characters.
Related errors
- 字符 " + method + " 不合法!函数的名称 function 不能为空且必须符合方法命名规范!总体必须为 f
- @having:value 的 value 中字符串 ${expression} 不合法!不允许传超过 100 个字符的
- 字符串 ${expression} 不合法!预编译模式下 @having:"column?value;function(
- 字符 ${method} 不合法!预编译模式下 @having:"column?value;function(arg0,
- 字符 ${method} 不合法!预编译模式下 @column:"column0,column1:alias;funct
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/1fa701cef11a1954.
Report an issue: GitHub.