{"record":{"id":"b83baf19d1b9d378","repo":"Tencent/APIJSON","slug":"refuse-value-rfs-key","errorCode":null,"errorMessage":"REFUSE:value 中出现了重复的 !{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":1064,"sourceCode":"\t\tSet<String> rkset = real.keySet(); // 解析内容并没有改变rkset\n\n\t\t// 解析不允许的字段<<<<<<<<<<<<<<<<<<<\n\t\tString[] refuses = StringUtil.split(refuse);\n\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}","sourceCodeStart":1046,"sourceCodeEnd":1082,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java#L1046-L1082","documentation":"Thrown while parsing the Request-table REFUSE list: the negated entry !key appears more than once (duplicate !key). REFUSE supports both refused keys and !key exceptions; duplicates are a config conflict.","triggerScenarios":"Request table REFUSE value contains \"!pictureUrl\" twice, e.g. REFUSE=\"!pictureUrl,name,!pictureUrl\".","commonSituations":"Merging REFUSE lists from two configs by concatenation; repeated edits appending the same exception; hand-editing without dedup.","solutions":["Deduplicate the REFUSE list so each !key appears once","Build REFUSE programmatically with a Set before saving to the Request table","Re-verify the whole REFUSE value for the related key/!key conflicts after editing"],"exampleFix":"-- before\nREFUSE=\"!pictureUrl,name,!pictureUrl\"\n-- after\nREFUSE=\"!pictureUrl,name\"","handlingStrategy":"validation","validationCode":"function lintRefuse(refuse /* string or list */) {\n  const seen = new Set();\n  for (let k of (Array.isArray(refuse) ? refuse : refuse.split(','))) {\n    k = k.trim(); if (!k) continue;\n    const neg = k.startsWith('!');\n    if (seen.has(k)) throw new Error(`duplicate REFUSE entry: ${k}`);\n    seen.add(k);\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Deduplicate REFUSE lists with a Set when generating configs","Run a config linter on Request tables before deploy"],"tags":["apijson","config","request-table","refuse"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}