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

  1. 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).
  2. 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.
  3. Wrap the dynamic @column value in a whitelist check before sending the request (see validation code).
  4. 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

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


AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14). Data as JSON: /api/errors/132daa8fa1ae2432. Report an issue: GitHub.