{"record":{"id":"46f61a5622c383f4","repo":"Tencent/APIJSON","slug":"errprefix-key-column-value","errorCode":null,"errorMessage":"{errPrefix} 中字符 '{key}' 对应的条件键值对 {column}:value 不存在！","messagePattern":"(.+?) 中字符 '(.+?)' 对应的条件键值对 (.+?):value 不存在！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java","lineNumber":3503,"sourceCode":"\t\t\t\t\t\t}\n\n\t\t\t\t\t\tallCount ++;\n\t\t\t\t\t\tif (allCount > maxCombineCount && maxCombineCount > 0) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(errPrefix + \" 中字符 '\" + s + \"' 不合法！\"\n\t\t\t\t\t\t\t\t\t+ \"其中 key 数量 \" + allCount + \" 已超过最大值，必须在条件键值对数量 0-\" + maxCombineCount + \" 内！\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tString column = key;\n\t\t\t\t\t\tint keyIndex = column.indexOf(\":\");\n\t\t\t\t\t\tcolumn = keyIndex > 0 ? column.substring(0, keyIndex) : column;\n\t\t\t\t\t\tObject value = conditionMap.get(column);\n\t\t\t\t\t\tString wi = \"\";\n\t\t\t\t\t\tif (value == null && conditionMap.containsKey(column) == false) { // 兼容@null\n\t\t\t\t\t\t\tisNot = false; // 以占位表达式为准\n\t\t\t\t\t\t\tsize++; // 兼容 key 数量判断\n\t\t\t\t\t\t\twi = keyIndex > 0 ? key.substring(keyIndex + 1) : \"\";\n\t\t\t\t\t\t\tif (StringUtil.isEmpty(wi)) {\n\t\t\t\t\t\t\t\tthrow new IllegalArgumentException(errPrefix + \" 中字符 '\"\n\t\t\t\t\t\t\t\t\t\t+ key + \"' 对应的条件键值对 \" + column + \":value 不存在！\");\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\twi = isHaving ? gainHavingItem(quote, table, alias, column, (String) value, containRaw)\n\t\t\t\t\t\t\t\t\t: gainWhereItem(column, value, method, verifyName);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (1.0f*allCount/size > maxCombineRatio && maxCombineRatio > 0) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(errPrefix + \" 中字符 '\" + s + \"' 不合法！\"\n\t\t\t\t\t\t\t\t\t+ \"其中 key 数量 \" + allCount + \" / 条件键值对数量 \" + size + \" = \" + (1.0f*allCount/size)\n\t\t\t\t\t\t\t\t\t+ \" 已超过 最大倍数，必须在条件键值对数量 0-\" + maxCombineRatio + \" 倍内！\");\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (StringUtil.isEmpty(wi, true)) {  // 转成 1=1 ?\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(errPrefix + \" 中字符 '\" + key\n\t\t\t\t\t\t\t\t\t+ \"' 对应的 \" + column + \":value 不是有效条件键值对！\");\n\t\t\t\t\t\t}\n","sourceCodeStart":3485,"sourceCodeEnd":3521,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L3485-L3521","documentation":"Each key in @combine is looked up in the conditionMap (the table's where/having entries). If the map neither contains the column nor maps it to null, the key is treated as a placeholder expression requiring a ':suffix' (e.g. \"col:condition\" syntax for @null-style placeholders); when that suffix is also empty, the key references a condition that does not exist and the expression cannot be built.","triggerScenarios":"@combine:\"name & status\" where the request object contains {\"id\":1} only — 'name' and 'status' have no key:value pairs. Or a typo: @combine:\"usrId\" while the condition key is \"userId\". For @having, the key must exist in the @having object.","commonSituations":"Renaming request keys but not the @combine string; building @combine from a different field list than the conditions; copy-pasting combine examples from docs without matching keys; deleting a filter field but leaving it in @combine.","solutions":["Make every key in @combine exactly match a key present in the same table object (or @having object).","Generate @combine from the actual condition key set, not a hardcoded list (see validation code).","Fix typos/case — matching is exact string equality on the column name before any ':'."],"exampleFix":"// before\n{\"User\":{\"id\":1,\"@combine\":\"id & name\"}}\n// after\n{\"User\":{\"id\":1,\"name\":\"a\",\"@combine\":\"id & name\"}}","handlingStrategy":"validation","validationCode":"Set<String> condKeys = tableObj.keySet().stream().filter(k -> !k.startsWith(\"@\")).collect(Collectors.toSet());\nfor (String k : combine.replaceAll(\"[()!]\", \" \").split(\"\\\\s*[&|]\\\\s*\")) {\n    String col = k.split(\":\")[0];\n    if (!condKeys.contains(col)) throw new IllegalStateException(\"@combine key not in conditions: \" + col);\n}","typeGuard":"function combineKeysExist(combine: string, condKeys: Set<string>): boolean {\n  return combine.replace(/[()!]/g, ' ').split(/\\s*[&|]\\s*/).every(t => condKeys.has(t.split(':')[0]));\n}","tryCatchPattern":null,"preventionTips":["Derive @combine from the actual condition map, never hardcode it.","Rename keys and combine strings together in one refactor.","Watch for exact case — key matching is case-sensitive string equality."],"tags":["apijson","combine","key-mismatch","request-argument"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}