{"record":{"id":"9e51a62f8bcc20fd","repo":"Tencent/APIJSON","slug":"errprefix-key-column-value-9e51a6","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":3518,"sourceCode":"\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\n\t\t\t\t\t\tInteger count = usedKeyCountMap.get(column);\n\t\t\t\t\t\tcount = count == null ? 1 : count + 1;\n\t\t\t\t\t\tif (count > maxCombineKeyCount && maxCombineKeyCount > 0) {\n\t\t\t\t\t\t\tthrow new IllegalArgumentException(errPrefix + \" 中字符 '\" + s + \"' 不合法！\"\n\t\t\t\t\t\t\t\t\t+ \"其中 '\" + column + \"' 重复引用，次数 \" + count\n\t\t\t\t\t\t\t\t\t+ \" 已超过最大值，必须在 0-\" + maxCombineKeyCount + \" 内！\");\n\t\t\t\t\t\t}\n\t\t\t\t\t\tusedKeyCountMap.put(column, count);\n\n\t\t\t\t\t\tresult += \"( \" + gainCondition(isNot, wi) + \" )\";\n\t\t\t\t\t\tisNot = false;\n\t\t\t\t\t\tfirst = false;\n\t\t\t\t\t}\n\n\t\t\t\t\tkey = \"\";","sourceCodeStart":3500,"sourceCodeEnd":3536,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java#L3500-L3536","documentation":"After resolving a @combine key, its SQL fragment wi is produced by gainWhereItem/gainHavingItem. If wi comes back empty (or blank), the key resolved to nothing usable — typically the condition value is an empty string, an empty container, or an operator with no effect — so the expression would contain an empty () group, and the request is rejected instead of emitting invalid SQL.","triggerScenarios":"@combine:\"remark & id\" where the request has \"remark\":\"\" (empty value) — the key exists (so 151 doesn't fire) but gainWhereItem returns an empty string. Similarly \"tag{}\":[] (empty array) or an @having entry whose value produces no SQL. StringUtil.isEmpty(wi, true) with trim=true is the test at line 3518.","commonSituations":"Optional filter fields sent as empty strings from HTML forms; dynamically added filters whose value is '' or []; JSON built with null/empty defaults that still create map entries.","solutions":["Omit keys with empty values from the request object entirely instead of sending \"key\":\"\".","Filter empty-string/empty-collection values out of the condition map before sending (see validation code).","If using placeholder keys ('col:suffix' form), ensure the suffix produces a real condition."],"exampleFix":"// before\n{\"User\":{\"id\":1,\"remark\":\"\",\"@combine\":\"id & remark\"}}\n// after\n{\"User\":{\"id\":1,\"@combine\":\"id\"}}","handlingStrategy":"validation","validationCode":"boolean effective = tableObj.entrySet().stream()\n    .filter(e -> !e.getKey().startsWith(\"@\"))\n    .allMatch(e -> e.getValue() != null && !\"\".equals(String.valueOf(e.getValue()).strip())\n        && !(e.getValue() instanceof Collection && ((Collection<?>) e.getValue()).isEmpty()));\nif (!effective) throw new IllegalStateException(\"empty condition value present\");","typeGuard":"function isEffectiveValue(v: unknown): boolean {\n  if (v === null || v === undefined) return false;\n  if (typeof v === 'string') return v.trim().length > 0;\n  if (Array.isArray(v)) return v.length > 0;\n  return true;\n}","tryCatchPattern":null,"preventionTips":["Strip empty-string/empty-array filter entries from request objects client-side.","Do not send form fields that the user left blank.","Exclude a key from @combine when its value may be empty."],"tags":["apijson","combine","empty-value","request-argument"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}