Tencent/APIJSON · error · IllegalArgumentException

{errPrefix} 中字符 '{key}' 不合法!左边缺少 & | 其中一个逻辑连接符!

Error message

{errPrefix} 中字符 '{key}' 不合法!左边缺少 & | 其中一个逻辑连接符!

What it means

In @combine parsing, a non-empty key was just terminated (by space, ')' or end) but this is not the first term and lastLogic <= 0, meaning no '&' or '|' was seen since the previous term. Every term after the first must be joined by a logical operator, so two keys appearing back-to-back (separated only by a parenthesis or start of a group) is a syntax error.

Source

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

			boolean first = true;
			boolean isNot = false;

			String key = "";
			while (i <= n) {  // "date> | (contactIdList<> & (name*~ | tag&$))"
				boolean isOver = i >= n;
				char c = isOver ? 0 : s.charAt(i);
				boolean isBlankOrRightParenthesis = c == ' ' || c == ')';
				if (isOver || isBlankOrRightParenthesis) {
					boolean isEmpty = StringUtil.isEmpty(key, true);
					if (isEmpty && last != ')') {
						throw new IllegalArgumentException(errPrefix + " 中字符 '" + (isOver ? s : s.substring(i))
								+ "' 不合法!" + (c == ' ' ? "空格 ' ' " : "右括号 ')'") + " 左边缺少条件 key !逻辑连接符 & | 左右必须各一个相邻空格!"
								+ "空格不能多也不能少!不允许首尾有空格,也不允许连续空格!左括号 ( 的右边 和 右括号 ) 的左边 都不允许有相邻空格!");
					}

					if (isEmpty == false) {
						if (first == false && lastLogic <= 0) {
							throw new IllegalArgumentException(errPrefix + " 中字符 "
									+ "'" + s.substring(i - key.length() - (isOver ? 1 : 0))
									+ "' 不合法!左边缺少 & | 其中一个逻辑连接符!");
						}

						allCount ++;
						if (allCount > maxCombineCount && maxCombineCount > 0) {
							throw new IllegalArgumentException(errPrefix + " 中字符 '" + s + "' 不合法!"
									+ "其中 key 数量 " + allCount + " 已超过最大值,必须在条件键值对数量 0-" + maxCombineCount + " 内!");
						}

						String column = key;
						int keyIndex = column.indexOf(":");
						column = keyIndex > 0 ? column.substring(0, keyIndex) : column;
						Object value = conditionMap.get(column);
						String wi = "";
						if (value == null && conditionMap.containsKey(column) == false) { // 兼容@null
							isNot = false; // 以占位表达式为准
							size++; // 兼容 key 数量判断

View on GitHub (pinned to 5284052872)

Solutions

  1. Insert '&' or '|' between every pair of terms, including right after ')': "(id | name) & tag".
  2. Use parentheses plus explicit operators everywhere; never rely on adjacency.
  3. Validate with a grammar check before sending (see validation code).

Example fix

// before
{"@combine":"(id)(name)"}
// after
{"@combine":"(id) & (name)"}
Defensive patterns

Strategy: validation

Validate before calling

// after tokenizing, ensure no two key/group tokens are adjacent without an operator between them
String normalized = combine.replaceAll("\\([^)]*\\)", "K").replaceAll("[!\\w]+", "K");
if (normalized.matches(".*KK.*")) throw new IllegalArgumentException("adjacent terms without & or |");

Type guard

function noAdjacentTerms(s: string): boolean {
  const norm = s.replace(/\([^)]*\)/g, 'K').replace(/[!\w]+/g, 'K');
  return !/KK/.test(norm);
}

Prevention

When it happens

Trigger: @combine:"id name" is caught earlier as a space-with-empty-key variant, but "(id)(name)", "(id) name", or "id!name" shapes reach here: the key text accumulates past a boundary without an operator. Also "a & (b c)" — inside the group, b is followed by c with no operator, so when c terminates and first==false with lastLogic==0, it throws at line 3482.

Common situations: Assuming juxtaposition means AND (as in some query DSLs) instead of requiring '&'; missing operator after a closing parenthesis; copy-paste deleting an operator between keys.

Related errors


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