{"record":{"id":"63ebdd83288e93d5","repo":"Tencent/APIJSON","slug":"method-name-rk-refuseset","errorCode":null,"errorMessage":"{method}请求，{name} 里面不允许传 {rk} 等{refuseSet}内的任何字段！","messagePattern":"(.+?)请求，(.+?) 里面不允许传 (.+?) 等(.+?)内的任何字段！","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java","lineNumber":1117,"sourceCode":"\n\t\t\t\t\trefuseSet.add(rfs);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// 解析不允许的字段>>>>>>>>>>>>>>>>>>>\n\n\t\tSet<String> onKeys = new LinkedHashSet<>();\n\n\t\t// 判断不允许传的key<<<<<<<<<<<<<<<<<<<<<<<<<\n\t\tfor (String rk : rkset) {\n\t\t\tif (rk == null || KEY_STRING.equals(rk) || KEY_TRIM.equals(rk)) {\n\t\t\t\t// ConcurrentModificationException  real.remove(rk);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (refuseSet.contains(rk)) { // 不允许的字段\n\t\t\t\tthrow new IllegalArgumentException(method + \"请求，\" + name\n\t\t\t\t\t\t+ \" 里面不允许传 \" + rk + \" 等\" + StringUtil.get(refuseSet) + \"内的任何字段！\");\n\t\t\t}\n\n\t\t\tif (KEY_COMBINE.equals(rk)) {\n\t\t\t\tthrow new UnsupportedOperationException(method + \" 请求，\" + rk + \" 不合法！\" +\n\t\t\t\t\t\t\"非开放请求不允许传 \" + KEY_COMBINE + \":value ！\");\n\t\t\t}\n\t\t\tif (KEY_KEY.equals(rk)) {\n\t\t\t\tthrow new UnsupportedOperationException(method + \" 请求，\" + rk + \" 不合法！\" +\n\t\t\t\t\t\t\"非开放请求不允许传 \" + KEY_KEY + \":value ！\");\n\t\t\t}\n\n\t\t\tObject rv = real.get(rk);\n\t\t\tif (rv != null && stringKeyList != null && stringKeyList.contains(rk)) {\n\t\t\t\trv = toJSONString(rv);\n\t\t\t}\n\t\t\tif (rv != null && trimKeyList != null && trimKeyList.contains(rk)) {\n\t\t\t\trv = StringUtil.trim(rv);","sourceCodeStart":1099,"sourceCodeEnd":1135,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java#L1099-L1135","documentation":"Thrown during request verification: the client sent a field that the Request table's REFUSE list forbids for this request. REFUSE is the server-side 'must NOT send' contract (with !key exceptions and !\"\" refuse-all-but-MUST mode).","triggerScenarios":"Request row for POST User has REFUSE=\"balance\" (or refuse-all !\"\" without the key in MUST) and the client posts {\"User\":{\"name\":\"a\",\"balance\":100}} — refuseSet contains 'balance' when rkset is scanned.","commonSituations":"Client reuses a full object (e.g. a row fetched via GET) as the POST/PUT body, including server-managed columns; frontend sends extra fields the backend owns (balance, role, createdAt); new refuse rule deployed while old clients still send the field.","solutions":["Strip refused fields from the payload before sending (build a minimal write object)","If the field should be client-writable, remove it from REFUSE (or add a !key exception) in the Request table","On the client, keep read models and write models separate so fetched objects are not echoed back"],"exampleFix":"// before  REFUSE=\"balance\"\n{\"User\":{\"name\":\"a\",\"balance\":100}}\n// after\n{\"User\":{\"name\":\"a\"}}","handlingStrategy":"validation","validationCode":"const REFUSED_FIELDS = ['balance', 'role']; // mirror of Request-table REFUSE\nfunction stripRefused(obj, refused) {\n  const out = { ...obj };\n  for (const f of refused) delete out[f];\n  return out;\n}","typeGuard":null,"tryCatchPattern":"catch (e) { if (/不允许传/.test(e.message)) { const rk = e.message.match(/传 (\\S+) 等/)?.[1]; retryWithout(rk); } else throw e; }","preventionTips":["Build write payloads from explicit field lists, never echo fetched rows back","Maintain a client-side copy of REFUSE per endpoint and strip before send","Coordinate REFUSE changes with client release notes"],"tags":["apijson","refuse","forbidden-field","request-table"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}