{"record":{"id":"e50bb5b920405658","repo":"Tencent/APIJSON","slug":"refuse-value-rfs-rfs-k","errorCode":null,"errorMessage":"REFUSE:value 中同时出现了 {rfs} 和 !{rfs} ！不允许重复，也不允许一个 key 和取反 !key 同时使用！","messagePattern":"REFUSE:value 中同时出现了 (.+?) 和 !(.+?) ！不允许重复，也不允许一个 key 和取反 !key 同时使用！","errorType":"validation","errorClass":"ConflictException","httpStatus":409,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java","lineNumber":1068,"sourceCode":"\t\tSet<String> refuseSet = new HashSet<String>();\n\n\t\tif (refuses != null && refuses.length > 0) {\n\t\t\tSet<String> notRefuseSet = new HashSet<String>();\n\n\t\t\tfor (String rfs : refuses) {\n\t\t\t\tif (rfs == null) {  // StringUtil.isEmpty(rfs, true) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tif (rfs.startsWith(\"!\")) {\n\t\t\t\t\trfs = rfs.substring(1);\n\n\t\t\t\t\tif (notRefuseSet.contains(rfs)) {\n\t\t\t\t\t\tthrow new ConflictException(REFUSE.name() + \":value 中出现了重复的 !\"\n                                + rfs + \" ！不允许重复，也不允许一个 key 和取反 !key 同时使用！\");\n\t\t\t\t\t}\n\t\t\t\t\tif (refuseSet.contains(rfs)) {\n\t\t\t\t\t\tthrow new ConflictException(REFUSE.name() + \":value 中同时出现了 \"\n                                + rfs + \" 和 !\" + rfs + \" ！不允许重复，也不允许一个 key 和取反 !key 同时使用！\");\n\t\t\t\t\t}\n\n\t\t\t\t\tif (rfs.equals(\"\")) { // 所有非 MUST\n                        // 对@key放行，@role,@column,自定义@position等， @key:{ \"Table\":{} } 不会解析内部\n\t\t\t\t\t\tfor (String key : rkset) {\n\t\t\t\t\t\t\tif (key == null || key.startsWith(\"@\") || notRefuseSet.contains(key)\n                                    || mustSet.contains(key) || objKeySet.contains(key)) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// 支持id ref: id{}@\n\t\t\t\t\t\t\tif (key.endsWith(\"@\") && mustSet.contains(key.substring(0, key.length() - 1))) {\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\trefuseSet.add(key);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {  // 排除 !key 后再禁传其它的","sourceCodeStart":1050,"sourceCodeEnd":1086,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java#L1050-L1086","documentation":"Thrown while parsing the Request-table REFUSE list: a plain key appears after the same key was already negated (!key seen earlier), i.e. both key and !key are configured. Refusing and allowing the same key at once is contradictory.","triggerScenarios":"REFUSE=\"!pictureUrl,pictureUrl\" — the negation is processed first, then the plain key hits the refuseSet-contains check.","commonSituations":"Config merge conflict where one branch refused a key and another un-refused it by adding the negation; copy-paste of refuse rules across request rows; misunderstanding !key semantics (it means 'refuse everything except', not 'un-refuse').","solutions":["Keep only one form: either the key or its !key negation, never both","Resolve the config-merge conflict at the source that generated the REFUSE value","Document that !key in REFUSE means 'exclude this key from the refuse-all set'"],"exampleFix":"-- before\nREFUSE=\"!pictureUrl,pictureUrl\"\n-- after\nREFUSE=\"!pictureUrl\"","handlingStrategy":"validation","validationCode":"function lintRefuse(refuse) {\n  const plain = new Set(), negated = new Set();\n  for (let k of refuse.split(',')) {\n    k = k.trim(); if (!k) continue;\n    if (k.startsWith('!')) { negated.add(k.slice(1)); if (plain.has(k.slice(1))) throw new Error(`key and !key both present: ${k}`); }\n    else { plain.add(k); if (negated.has(k)) throw new Error(`key and !key both present: ${k}`); }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never 'undo' a refuse by appending !key — remove the original entry instead","Review REFUSE values after merging configs from multiple sources"],"tags":["apijson","config","request-table","refuse"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}