Tencent/APIJSON · error · IllegalArgumentException

HEAD请求: 字符 不合法!预编译模式下 @column:value 中 value里面用 , 分割的每一项…

Error message

HEAD请求: 字符 {alias} 不合法!预编译模式下 @column:value 中 value里面用 , 分割的每一项 column:alias 中 column 必须是1个单词!如果有alias,则alias也必须为1个单词!并且不要有多余的空格!

What it means

Thrown while building the SELECT COUNT clause for a HEAD/HEADS request in prepared mode (AbstractSQLConfig.gainColumnString). Each comma-separated item in @column:value is split at the last ':' into origin and alias; if an alias exists and StringUtil.isName(alias) is false (i.e. it is not a single identifier word), this IllegalArgumentException is thrown before any SQL is generated. It exists to prevent SQL injection through crafted alias segments in HEAD count queries.

Solutions

  1. Remove the alias or make it a single word: "@column":"userId:uid" instead of "userId:my uid".
  2. Remove all spaces around ':' — "id:alias" not "id : alias" or "id: alias".
  3. For expressions needing colons or spaces (e.g. date_format(date,'%Y-%m-%d %H:%i')), whitelist the whole expression server-side via RAW_MAP / @raw so the parser skips it.
  4. For a plain count, drop @column entirely — count(*) is generated when column is null or contains a comma.

Example fix

// before
{"User":{"@column":"name : display name"}}
// after
{"User":{"@column":"name:displayName"}}
Defensive patterns

Strategy: validation

Validate before calling

const NAME = /^[A-Za-z][A-Za-z0-9_]*$/;
const okHeadColumn = (col) => col.split(',').every(item => { const i = item.lastIndexOf(':'); if (i < 0) return NAME.test(item); return NAME.test(item.slice(0, i)) && NAME.test(item.slice(i + 1)); });
if (!okHeadColumn(req.User['@column'])) throw new Error('bad HEAD @column');

Type guard

null

Try / catch

catch (IllegalArgumentException e) { respond 400 with e.getMessage(); log offending @column value; }

Prevention

When it happens

Trigger: A HEAD/HEADS request whose table object contains "@column":"id : my alias" or "@column":"userId:u1 u2" — any alias containing spaces, punctuation, operators, or multiple words. Also triggered by URLs like /head/User#@column={"@column":"date_format(date,'%Y-%m-%d'):my alias"} when not whitelisted via @raw.

Common situations: Frontend developers copying a SQL expression like DATE_FORMAT(date,'%Y-%m-%d %H:%i:%s') AS formattedDate into @column for a count endpoint; forgetting that HEAD only supports column or single function expressions, not arbitrary aliases; trailing spaces after the colon introduced by string concatenation in client code.

Related errors


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

Appendix: source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:2322

				List<String> raw = getRaw();
				boolean containRaw = raw != null && raw.contains(KEY_COLUMN);

				for (String c : column) {
					if (containRaw) {
						// 由于 HashMap 对 key 做了 hash 处理,所以 get 比 containsValue 更快
						if ("".equals(RAW_MAP.get(c)) || RAW_MAP.containsValue(c)) {  // newSQLConfig<T, M, L> 提前处理好的
							//排除@raw中的值,以避免使用date_format(date,'%Y-%m-%d %H:%i:%s') 时,冒号的解析出错
							//column.remove(c);
							continue;
						}
					}

					int index = c.lastIndexOf(":"); //StringUtil.split返回数组中,子项不会有null
					String origin = index < 0 ? c : c.substring(0, index);
					String alias = index < 0 ? null : c.substring(index + 1);

					if (alias != null && StringUtil.isName(alias) == false) {
						throw new IllegalArgumentException("HEAD请求: 字符 " + alias
								+ " 不合法!预编译模式下 @column:value 中 value里面用 , 分割的每一项"
								+ " column:alias 中 column 必须是1个单词!如果有alias,则alias也必须为1个单词!并且不要有多余的空格!");
					}

					if (StringUtil.isName(origin) == false) {
						int start = origin.indexOf("(");
						if (start < 0 || origin.lastIndexOf(")") <= start) {
							throw new IllegalArgumentException("HEAD请求: 字符" + origin
									+ " 不合法!预编译模式下 @column:value 中 value里面用 , 分割的每一项"
									+ " column:alias 中 column 必须是1个单词!"
									+ "如果有alias,则 alias 也必须为1个单词!并且不要有多余的空格!");
						}

						if (start > 0 && StringUtil.isName(origin.substring(0, start)) == false) {
							throw new IllegalArgumentException("HEAD请求: 字符 " + origin.substring(0, start)
									+ " 不合法!预编译模式下 @column:value 中 value里面用 , 分割的每一项"
									+ " column:alias 中 column 必须是1个单词!如果有alias,则alias也必须为1个单词!并且不要有多余的空格!");
						}

View on GitHub (pinned to 5284052872)