{"record":{"id":"e342632723ef9fbf","repo":"Tencent/APIJSON","slug":"method-rk-key-fun","errorCode":null,"errorMessage":"{method} 请求，{rk} 不合法！非开放请求不允许传远程函数 key():\"fun()\" ！","messagePattern":"(.+?) 请求，(.+?) 不合法！非开放请求不允许传远程函数 key\\(\\):\"fun\\(\\)\" ！","errorType":"validation","errorClass":"UnsupportedOperationException","httpStatus":400,"severity":"error","filePath":"APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java","lineNumber":1140,"sourceCode":"\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);\n\t\t\t}\n\n\t\t\t// 不允许传远程函数，只能后端配置\n\t\t\tif (rk.endsWith(\"()\") && rv instanceof String) {\n\t\t\t\tthrow new UnsupportedOperationException(method + \" 请求，\" + rk + \" 不合法！\" +\n                        \"非开放请求不允许传远程函数 key():\\\"fun()\\\" ！\");\n\t\t\t}\n\n\t\t\t// 不在target内的 key:{}\n\t\t\tif (rk.startsWith(\"@\") == false && rk.endsWith(\"@\") == false && objKeySet.contains(rk) == false) {\n\t\t\t\tif (rv instanceof Map<?, ?>) {\n\t\t\t\t\tthrow new UnsupportedOperationException(method + \" 请求，\"\n                            + name + \" 里面不允许传 \" + rk + \":{} ！\");\n\t\t\t\t}\n\t\t\t\tif ((method == POST || method == PUT)\n                        && rv instanceof List<?> && isArrayKey(rk)) {\n\t\t\t\t\tthrow new UnsupportedOperationException(method + \" 请求，\" + name + \" 里面不允许 \"\n                            + rk + \":[] 等未定义的 Table[]:[{}] 批量操作键值对！\");\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// 先让其它操作符完成\n//\t\t\tif (rv != null) { // || nulls.contains(rk)) {","sourceCodeStart":1122,"sourceCodeEnd":1158,"githubUrl":"https://github.com/Tencent/APIJSON/blob/5284052872898eddc449a58f629e5c8d588b8e22/APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java#L1122-L1158","documentation":"Thrown when a non-open request contains a remote-function pair — a key ending in () with a String value, e.g. \"isPrime()\": \"isPrime(id)\". Remote functions must be configured server-side; client-supplied ones would let callers execute arbitrary registered functions.","triggerScenarios":"Request body includes {\"User\":{\"id\":1,\"isPrime()\":\"isPrime(id)\"}} on a non-open request — rk.endsWith(\"()\") && rv instanceof String.","commonSituations":"Copying demo payloads from APIJSON docs that showcase remote functions; frontend computing derived values by invoking server functions per row; testing function tags against a locked tag.","solutions":["Remove all key():\"fun()\" entries from the client request","Ask the backend to register the function in the Function table and reference it from the Request-table config","Compute derived values client-side or via a dedicated endpoint"],"exampleFix":"// before\n{\"User\":{\"id\":1,\"isPrime()\":\"isPrime(id)\"}}\n// after\n{\"User\":{\"id\":1}}","handlingStrategy":"validation","validationCode":"function stripRemoteFunctions(obj) {\n  const out = {};\n  for (const k of Object.keys(obj)) if (!k.endsWith('()')) out[k] = obj[k];\n  return out;\n}","typeGuard":"const isRemoteFunctionKey = (k) => k.endsWith('()');","tryCatchPattern":null,"preventionTips":["Never send key():\"fun()\" pairs from clients on closed requests","Ask backend to register needed functions in the Function table and bind them server-side"],"tags":["apijson","remote-function","security","open-request"],"backgroundTag":null,"analyzedSha":"5284052872898eddc449a58f629e5c8d588b8e22","analyzedAt":"2026-08-14T15:15:29.577Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}