Tencent/APIJSON · error · IllegalArgumentException
字符 {ck} 不合法!预编译模式下 @column:"column0,column1:alias;function0(
Error message
字符 {ck} 不合法!预编译模式下 @column:"column0,column1:alias;function0(arg0,arg1,...);function1(...):alias..." 中所有 arg 都必须是1个不以 _ 开头的单词 或者符合正则表达式 {PATTERN_FUNCTION} 且不包含连续减号 -- !DISTINCT 必须全大写,且后面必须有且只有 1 个空格!其它情况不允许空格! What it means
Thrown while parsing @column:"..." in SQLConfig when the request runs in prepared mode (isPrepared() == true). After splitting a column item on ':' into origin/alias, a non-column token (e.g. a function argument such as MAX(x)) is rejected because it starts with '_' or contains the consecutive minus '--'. This is an SQL-injection guard: '_' prefixes and '--' (SQL comment) are the classic payloads smuggled through column expressions.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:2738
else {
origin = ck;
alias = null;
if (allowAlias) {
int index = isColumn ? ck.lastIndexOf(":") : -1; //StringUtil.split返回数组中,子项不会有null
origin = index < 0 ? ck : ck.substring(0, index); //获取 : 之前的
alias = index < 0 ? null : ck.substring(index + 1);
if (isPrepared()) {
if (isColumn) {
if (StringUtil.isName(origin) == false || (alias != null && StringUtil.isName(alias) == false)) {
throw new IllegalArgumentException("字符 " + ck + " 不合法!"
+ "预编译模式下 @column:value 中 value里面用 , 分割的每一项"
+ " column:alias 中 column 必须是1个单词!如果有alias,则alias也必须为1个单词!"
+ "关键字必须全大写,且以空格分隔的参数,空格必须只有 1 个!其它情况不允许空格!");
}
} else {
if (origin.startsWith("_") || origin.contains("--")) {
// || PATTERN_FUNCTION.matcher(origin).matches() == false) {
throw new IllegalArgumentException("字符 " + ck + " 不合法!"
+ "预编译模式下 @column:\"column0,column1:alias;function0(arg0,arg1,...);function1(...):alias...\""
+ " 中所有 arg 都必须是1个不以 _ 开头的单词 或者符合正则表达式 "
+ PATTERN_FUNCTION + " 且不包含连续减号 -- !" +
"DISTINCT 必须全大写,且后面必须有且只有 1 个空格!其它情况不允许空格!");
}
}
}
}
// 以空格分割参数
String[] mkes = containRaw ? StringUtil.split(ck, " ", true) : new String[]{ ck };
//如果参数中含有空格(少数情况) 比如 fun(arg1, arg2,arg3,arg4) 中的 arg1 arg2 arg3,比如 DISTINCT id
if (mkes != null && mkes.length >= 2) {
origin = parseArgsSplitWithSpace(mkes);
} else {
String mk = RAW_MAP.get(origin);
if (mk != null) { // newSQLConfig<T, M, L> 提前处理好的View on GitHub (pinned to 5284052872)
Solutions
- Remove any '--' sequence: write subtraction as a single value or compute it in code, not inside @column (e.g. use 'price-1' is fine, 'price--1' is not).
- If a real column name starts with '_', alias it in the database or map it via @column:"`_col`" only if raw mode is acceptable — in prepared mode rename the column instead.
- Wrap the dynamic @column value in a whitelist check before sending the request (see validation code).
- If you own the deployment and must allow such expressions, switch the table/request out of prepared mode only after reviewing the injection risk (setIsPrepared(false) is discouraged).
Example fix
// before
{"User":{"@column":"date_add(registerDate, INTERVAL _1 DAY):d, remark--"}}
// after
{"User":{"@column":"date_add(registerDate, INTERVAL 1 DAY):d, remark"}} Defensive patterns
Strategy: validation
Validate before calling
String PATTERN_FUNCTION = "^(\\w+\\(\\s*(DISTINCT\\s)?\\w+(\\s*,\\s*(\\w+|'[^']*'))*\\s*\\))$";
boolean ok = Arrays.stream(columnExpr.split(",")).allMatch(item -> {
String origin = item.contains(":") ? item.substring(0, item.indexOf(':')) : item;
return !origin.trim().startsWith("_") && !origin.contains("--")
&& (origin.matches("\\w+") || origin.matches(PATTERN_FUNCTION));
});
if (!ok) throw new IllegalArgumentException("unsafe @column item"); Type guard
function isSafeColumnItem(item: string): boolean {
const origin = item.includes(':') ? item.slice(0, item.indexOf(':')) : item;
return !origin.startsWith('_') && !origin.includes('--') && /^[A-Za-z0-9_$]+$/.test(origin);
} Try / catch
catch (IllegalArgumentException e) { log.warn("rejected @column: {}", columnExpr, e); /* fall back to a plain column list */ } Prevention
- Whitelist @column items against ^\w+$ or the function pattern before sending.
- Never interpolate user input into @column; map user choices to fixed column names.
- Keep subtraction/SQL comments out of @column expressions.
When it happens
Trigger: A GET/POST request body like {"@column":"max(_score)"} or {"@column":"price--"} (or any function-arg token in @column that starts with _ or contains --) while the Parser runs with prepared statements enabled (default in production via AbstractSQLExecutor). Only the non-isColumn branch (origin present, not simple column:alias) triggers it, at AbstractSQLConfig.java:2738.
Common situations: Developers copying a raw SQL fragment like 'DATE_ADD(date,INTERVAL -1 DAY)' or 'a-b' into @column; using columns that legitimately start with underscore; testing locally with raw mode then deploying to prepared mode where validation is stricter; attempt to comment out trailing SQL with --.
Related errors
- 字符 {origin} 不合法!预编译模式下 @column:"column0,column1:alias;functi
- @group:value 中 value里面用 , 分割的每一项都必须是1个单词!并且不要有空格!
- 预编译模式下 @order:value 中 {item} 不合法! value 里面用 , 分割的每一项必须是 随机函数
- Cannot convert value of type " + value.getClass().getName()
- 字符 " + function + " 不合法!
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/132daa8fa1ae2432.
Report an issue: GitHub.