Tencent/APIJSON · error · IllegalArgumentException

{table}:{ @combine:'{combine}' } 中条件 key:value 数量 {size} 已超过

Error message

{table}:{ @combine:'{combine}' } 中条件 key:value 数量 {size} 已超过最大数量,必须在 0-{maxCount} 内!

What it means

Before parsing a @combine/@having expression, parseCombineExpression() compares the number of condition key:value pairs in the where/having map against maxWhereCount or maxHavingCount. If maxCount > 0 and size exceeds it, the request is rejected. This is a resource/DoS guard limiting how many conditions one query may carry (configured via the SQLConfig max-* getters, often from project properties).

Source

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

	protected String parseCombineExpression(RequestMethod method, String quote, String table, String alias
			, Map<String, Object> conditionMap, String combine, boolean verifyName, boolean containRaw, boolean isHaving) throws Exception {

		String errPrefix = table + (isHaving ? ":{ @having:{ " : ":{ ") + "@combine:'" + combine + (isHaving ? "' } }" : "' }");
		String s = StringUtil.get(combine);
		if (s.startsWith(" ") || s.endsWith(" ") ) {
			throw new IllegalArgumentException(errPrefix + " 中字符 '" + s
					+ "' 不合法!不允许首尾有空格,也不允许连续空格!空格不能多也不能少!"
					+ "逻辑连接符 & | 左右必须各一个相邻空格!左括号 ( 右边和右括号 ) 左边都不允许有相邻空格!");
		}

		if (conditionMap == null) {
			conditionMap = new HashMap<>();
		}
		int size = conditionMap.size();

		int maxCount = isHaving ? getMaxHavingCount() : getMaxWhereCount();
		if (maxCount > 0 && size > maxCount) {
			throw new IllegalArgumentException(table + (isHaving ? ":{ @having:{ " : ":{ ") + "key0:value0, key1:value1... " + combine
					+ (isHaving ? " } }" : " }") + " 中条件 key:value 数量 " + size + " 已超过最大数量,必须在 0-" + maxCount + " 内!");
		}

		String result = "";

		List<Object> preparedValues = getPreparedValueList();
		if (preparedValues == null && isHaving == false) {
			preparedValues = new ArrayList<>();
		}

		Map<String, Integer> usedKeyCountMap = new HashMap<>(size);

		int n = s.length();
		if (n > 0) {
			if (isHaving == false) {  // 只收集表达式条件值
				setPreparedValueList(new ArrayList<>());  // 必须反过来,否则 JOIN ON 内部 @combine 拼接后顺序错误
			}

View on GitHub (pinned to 5284052872)

Solutions

  1. Reduce the number of condition keys sent (paginate, use $ IN-lists like "id{}":[1,2,3] which counts as one key).
  2. If legitimate, raise maxWhereCount/maxHavingCount in the server-side APIJSON configuration (Verifier/Parser properties) rather than removing the guard.
  3. Split the query into several requests each under the cap.
  4. Pre-count condition keys client-side before sending (see validation code).

Example fix

// before (many keys)
{"User":{"id1":1,"id2":2,"id3":3, ..., "id50":50, "@combine":"..."}}
// after (IN list, 1 key)
{"User":{"id{}": [1,2,3, ..., 50]}}
Defensive patterns

Strategy: validation

Validate before calling

int size = tableObj.keySet().stream().filter(k -> !k.startsWith("@")).mapToInt(k -> 1).sum();
if (MAX_WHERE_COUNT > 0 && size > MAX_WHERE_COUNT) throw new IllegalStateException("too many conditions: " + size);

Type guard

function withinLimit(count: number, max: number): boolean { return max <= 0 || count <= max; }

Try / catch

catch (IllegalArgumentException e) { /* split request or reduce conditions, then retry */ }

Prevention

When it happens

Trigger: A table object with more where keys than the configured maximum, e.g. 50 conditions while getMaxWhereCount() returns 30 (defaults come from APIJSONParser/Verifier properties such as maxWhereCount). Any @combine on that object reaches this check even if well-formed. Note size is conditionMap.size() before parsing starts.

Common situations: Bulk-search screens letting users add unlimited filter fields; batch jobs posting many id<> conditions; lowering/increasing server-side limits after deploy while clients still send wide filters. Newer APIJSON versions added these configurable caps, so code that worked before an upgrade can start failing.

Related errors


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