Tencent/APIJSON · error · IllegalArgumentException
{errPrefix} 中字符 '{s}' 不合法!其中 '{column}' 重复引用,次数 {count} 已超过最
Error message
{errPrefix} 中字符 '{s}' 不合法!其中 '{column}' 重复引用,次数 {count} 已超过最大值,必须在 0-{maxCombineKeyCount} 内! What it means
usedKeyCountMap tracks how many times each column is referenced while parsing @combine. After incrementing, if count exceeds maxCombineKeyCount (>0), the request is rejected. This is a per-key cap — stricter and earlier than the aggregate ratio check (error 152) — preventing a single column from being repeated dozens of times in one expression.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:3525
wi = isHaving ? gainHavingItem(quote, table, alias, column, (String) value, containRaw)
: gainWhereItem(column, value, method, verifyName);
}
if (1.0f*allCount/size > maxCombineRatio && maxCombineRatio > 0) {
throw new IllegalArgumentException(errPrefix + " 中字符 '" + s + "' 不合法!"
+ "其中 key 数量 " + allCount + " / 条件键值对数量 " + size + " = " + (1.0f*allCount/size)
+ " 已超过 最大倍数,必须在条件键值对数量 0-" + maxCombineRatio + " 倍内!");
}
if (StringUtil.isEmpty(wi, true)) { // 转成 1=1 ?
throw new IllegalArgumentException(errPrefix + " 中字符 '" + key
+ "' 对应的 " + column + ":value 不是有效条件键值对!");
}
Integer count = usedKeyCountMap.get(column);
count = count == null ? 1 : count + 1;
if (count > maxCombineKeyCount && maxCombineKeyCount > 0) {
throw new IllegalArgumentException(errPrefix + " 中字符 '" + s + "' 不合法!"
+ "其中 '" + column + "' 重复引用,次数 " + count
+ " 已超过最大值,必须在 0-" + maxCombineKeyCount + " 内!");
}
usedKeyCountMap.put(column, count);
result += "( " + gainCondition(isNot, wi) + " )";
isNot = false;
first = false;
}
key = "";
lastLogic = 0;
if (isOver) {
break;
}
}
View on GitHub (pinned to 5284052872)
Solutions
- Reference each key at most maxCombineKeyCount times; hoist common terms: "a & (b | c | d)" instead of repeating a.
- Raise maxCombineKeyCount server-side if repetition is legitimate.
- Lint generated combine strings for duplicate-key counts before sending (see validation code).
Example fix
// before
{"@combine":"(a & b) | (a & c) | (a & d)"}
// after
{"@combine":"a & (b | c | d)"} Defensive patterns
Strategy: validation
Validate before calling
Map<String, Long> counts = Arrays.stream(combine.replaceAll("[()!]", " ").split("\\s*[&|]\\s*"))
.collect(Collectors.groupingBy(k -> k.split(":")[0], Collectors.counting()));
if (counts.values().stream().anyMatch(c -> MAX_COMBINE_KEY_COUNT > 0 && c > MAX_COMBINE_KEY_COUNT))
throw new IllegalStateException("key referenced too often"); Type guard
function keyCountsWithin(combine: string, max: number): boolean {
const m = new Map<string, number>();
for (const t of combine.replace(/[()!]/g, ' ').split(/\s*[&|]\s*/)) {
const k = t.split(':')[0]; m.set(k, (m.get(k) ?? 0) + 1);
if (m.get(k)! > max) return false;
}
return true;
} Prevention
- Factor shared keys out with parentheses: a & (b | c) not (a&b) | (a&c).
- Set per-key reference budgets in your expression generator.
- Read maxCombineKeyCount from server config.
When it happens
Trigger: @combine:"a & a & a & a & a" with maxCombineKeyCount set (e.g. 5 by default in hardened deployments): the 6th reference to 'a' throws at line 3525. Distinct keys are unaffected; only repetition of one column counts.
Common situations: Generated expressions that fan one flag into many branches ("(a & b) | (a & c) | (a & d) ..."); security tuning that lowered maxCombineKeyCount; upgrading to an APIJSON version where per-key caps became configurable/enabled.
Related errors
- {errPrefix} 中字符 '{s}' 不合法!其中 key 数量 {allCount} 已超过最大值,必须在条件键
- {errPrefix} 中字符 '{s}' 不合法!不允许首尾有空格,也不允许连续空格!空格不能多也不能少!逻辑连接符
- {table}:{ @combine:'{combine}' } 中条件 key:value 数量 {size} 已超过
- {errPrefix} 中字符 '{s}' 不合法!空格 ' ' 左边缺少条件 key !逻辑连接符 & | 左右必须各
- {errPrefix} 中字符 '{key}' 不合法!左边缺少 & | 其中一个逻辑连接符!
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/8f311fd687a7de10.
Report an issue: GitHub.