{"record":{"id":"730eeaf0271009d0","repo":"Tencent/APIJSON","slug":"table-combine-combine-key-value","errorCode":null,"errorMessage":"{table}:{ @combine:'{combine}' } 中条件 key:value 数量 {size} 已超过最大数量，必须在 0-{maxCount} 内！","messagePattern":"(.+?):(.+?)' \\} 中条件 key:value 数量 (.+?) 已超过最大数量，必须在 0-(.+?) 内！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":3433,"sourceCode":"\tprotected String parseCombineExpression(RequestMethod method, String quote, String table, String alias\n\t\t\t, Map<String, Object> conditionMap, String combine, boolean verifyName, boolean containRaw, boolean isHaving) throws Exception {\n\n\t\tString errPrefix = table + (isHaving ? \":{ @having:{ \" : \":{ \") + \"@combine:'\" + combine + (isHaving ? \"' } }\" : \"' }\");\n\t\tString s = StringUtil.get(combine);\n\t\tif (s.startsWith(\" \") || s.endsWith(\" \") ) {\n\t\t\tthrow new IllegalArgumentException(errPrefix + \" 中字符 '\" + s\n\t\t\t\t\t+ \"' 不合法！不允许首尾有空格，也不允许连续空格！空格不能多也不能少！\"\n\t\t\t\t\t+ \"逻辑连接符 & | 左右必须各一个相邻空格！左括号 ( 右边和右括号 ) 左边都不允许有相邻空格！\");\n\t\t}\n\n\t\tif (conditionMap == null) {\n\t\t\tconditionMap = new HashMap<>();\n\t\t}\n\t\tint size = conditionMap.size();\n\n\t\tint maxCount = isHaving ? getMaxHavingCount() : getMaxWhereCount();\n\t\tif (maxCount > 0 && size > maxCount) {\n\t\t\tthrow new IllegalArgumentException(table + (isHaving ? \":{ @having:{ \" : \":{ \") + \"key0:value0, key1:value1... \" + combine\n\t\t\t\t\t+ (isHaving ? \" } }\" : \" }\") + \" 中条件 key:value 数量 \" + size + \" 已超过最大数量，必须在 0-\" + maxCount + \" 内！\");\n\t\t}\n\n\t\tString result = \"\";\n\n\t\tList<Object> preparedValues = getPreparedValueList();\n\t\tif (preparedValues == null && isHaving == false) {\n\t\t\tpreparedValues = new ArrayList<>();\n\t\t}\n\n\t\tMap<String, Integer> usedKeyCountMap = new HashMap<>(size);\n\n\t\tint n = s.length();\n\t\tif (n > 0) {\n\t\t\tif (isHaving == false) {  // 只收集表达式条件值\n\t\t\t\tsetPreparedValueList(new ArrayList<>());  // 必须反过来，否则 JOIN ON 内部 @combine 拼接后顺序错误\n\t\t\t}\n","sourceCodeStart":3415,"sourceCodeEnd":3451,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L3415-L3451","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reduce the number of condition keys sent (paginate, use $ IN-lists like \"id{}\":[1,2,3] which counts as one key).","If legitimate, raise maxWhereCount/maxHavingCount in the server-side APIJSON configuration (Verifier/Parser properties) rather than removing the guard.","Split the query into several requests each under the cap.","Pre-count condition keys client-side before sending (see validation code)."],"exampleFix":"// before (many keys)\n{\"User\":{\"id1\":1,\"id2\":2,\"id3\":3, ..., \"id50\":50, \"@combine\":\"...\"}}\n// after (IN list, 1 key)\n{\"User\":{\"id{}\": [1,2,3, ..., 50]}}","handlingStrategy":"validation","validationCode":"int size = tableObj.keySet().stream().filter(k -> !k.startsWith(\"@\")).mapToInt(k -> 1).sum();\nif (MAX_WHERE_COUNT > 0 && size > MAX_WHERE_COUNT) throw new IllegalStateException(\"too many conditions: \" + size);","typeGuard":"function withinLimit(count: number, max: number): boolean { return max <= 0 || count <= max; }","tryCatchPattern":"catch (IllegalArgumentException e) { /* split request or reduce conditions, then retry */ }","preventionTips":["Track your deployment's maxWhereCount/maxHavingCount config and check condition count client-side.","Collapse repeated keys into IN-lists (\"id{}\": [...]).","Paginate bulk operations instead of wide WHERE maps."],"tags":["apijson","limits","where-clause","combine","configuration"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}