Tencent/APIJSON · error · IllegalArgumentException

@group:value 中 value里面用 , 分割的每一项都必须是1个单词!并且不要有空格!

Error message

@group:value 中 value里面用 , 分割的每一项都必须是1个单词!并且不要有空格!

What it means

In prepared mode (isPrepared()), AbstractSQLConfig validates every comma-separated item of @group:value with StringUtil.isName — each must be a single identifier word. GROUP BY items cannot be bound as ? parameters, so malformed items would otherwise allow SQL injection.

Source

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

				//		joinGroup += (first ? "" : ", ") + c;
				//		first = false;
				//	}
				//}
			}
		}


		group = StringUtil.trim(group);
		String[] keys = StringUtil.split(group);
		if (keys == null || keys.length <= 0) {
			return StringUtil.isEmpty(joinGroup, true) ? "" : (hasPrefix ? " GROUP BY " : "") + joinGroup;
		}

		for (int i = 0; i < keys.length; i++) {
			if (isPrepared()) {
				// 不能通过 ? 来代替,因为SQLExecutor<T, M, L> statement.setString后 GROUP BY 'userId' 有单引号,只能返回一条数据,必须去掉单引号才行!
				if (StringUtil.isName(keys[i]) == false) {
					throw new IllegalArgumentException("@group:value 中 value里面用 , 分割的每一项都必须是1个单词!并且不要有空格!");
				}
			}

			keys[i] = gainKey(keys[i]);
		}

		return (hasPrefix ? " GROUP BY " : "") + StringUtil.concat(StringUtil.get(keys), joinGroup, ", ");
	}

	@Override
	public String getHavingCombine() {
		return havingCombine;
	}
	@Override
	public AbstractSQLConfig<T, M, L> setHavingCombine(String havingCombine) {
		this.havingCombine = havingCombine;
		return this;
	}

View on GitHub (pinned to 5284052872)

Solutions

  1. Use only bare column names: "@group": "userId,date"
  2. Put aggregate functions in @column (e.g. "count(*):count") and group by plain columns only
  3. For expressions that cannot be a plain name, pre-define them in backend RAW_MAP and reference via @raw

Example fix

// before
{"@column": "count(*)", "@group": "count(*)"}
// after
{"@column": "count(*):count", "@group": "userId"}
Defensive patterns

Strategy: validation

Validate before calling

const isName = s => /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);
for (const item of String(obj['@group'] ?? '').split(',')) {
  if (item && !isName(item.trim())) throw new Error(`@group item '${item}' must be a bare column name`);
}

Type guard

const isGroupItemValid = s => /^[A-Za-z_][A-Za-z0-9_]*$/.test(s);

Try / catch

try { await api.get(req); } catch (e) { if (e.message.includes('@group')) sanitizeListField(req, '@group'); else throw e; }

Prevention

When it happens

Trigger: GET request with "@group": "count(*)", "@group": "user id" (space), "@group": "userId;drop" or any item with quotes/dashes/spaces instead of a bare column name.

Common situations: Frontend passes an aggregated expression into @group instead of @column; users paste SQL fragments; column aliases with hyphens or dots.

Related errors


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