Tencent/APIJSON · error · UnsupportedOperationException
{method} 请求,{name} 里面不允许 {rk}:[] 等未定义的 Table[]:[{}] 批量操作键值对!
Error message
{method} 请求,{name} 里面不允许 {rk}:[] 等未定义的 Table[]:[{}] 批量操作键值对! What it means
Thrown by AbstractVerifier.verifyRepeat/parse key-sweep when a POST or PUT request body contains a Table[] batch key (a key ending in '[]' whose value is a List, e.g. 'User[]':[{...},{...}]) inside an object whose server-side Request-table structure config does not define that key. The verifier only accepts object keys declared in the target structure (objKeySet), plus @-prefixed/suffixed reserved keys; an undeclared array key used for batch insert/update is rejected because the backend never authorized batch operations there.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractVerifier.java:1152
if (rv != null && trimKeyList != null && trimKeyList.contains(rk)) {
rv = StringUtil.trim(rv);
}
// 不允许传远程函数,只能后端配置
if (rk.endsWith("()") && rv instanceof String) {
throw new UnsupportedOperationException(method + " 请求," + rk + " 不合法!" +
"非开放请求不允许传远程函数 key():\"fun()\" !");
}
// 不在target内的 key:{}
if (rk.startsWith("@") == false && rk.endsWith("@") == false && objKeySet.contains(rk) == false) {
if (rv instanceof Map<?, ?>) {
throw new UnsupportedOperationException(method + " 请求,"
+ name + " 里面不允许传 " + rk + ":{} !");
}
if ((method == POST || method == PUT)
&& rv instanceof List<?> && isArrayKey(rk)) {
throw new UnsupportedOperationException(method + " 请求," + name + " 里面不允许 "
+ rk + ":[] 等未定义的 Table[]:[{}] 批量操作键值对!");
}
}
// 先让其它操作符完成
// if (rv != null) { // || nulls.contains(rk)) {
// onKeys.add(rk);
// }
}
// 判断不允许传的key>>>>>>>>>>>>>>>>>>>>>>>>>
// 校验与修改Request<<<<<<<<<<<<<<<<<
// 在tableKeySet校验后操作,避免 导致put/add进去的Table 被当成原Request的内容
real = operate(TYPE, type, real, parser);
real = operate(VERIFY, verify, real, parser);
real = operate(INSERT, insert, real, parser);View on GitHub (pinned to 5284052872)
Solutions
- Add the batch key to the server Request table, e.g. UPDATE Request SET structure = json_set(structure, '$.User[]', json_array()) WHERE method=1 AND tag='User' (or re-run the SysTable/Request SQL script), then retry the POST/PUT.
- Remove the 'Table[]':[{}] pair from the request and issue one single-object POST/PUT per row instead.
- Move the batch pair into the correct top-level object that actually declares it (e.g. send it as a sibling tag declared in the structure, not nested inside another table's object).
- If the key is not meant as a batch op, rename it so it does not end with '[]' or change its value from a List to a Map/scalar where appropriate.
Example fix
// before (request rejected: User[] not declared in structure)
{"tag":"Moment","Moment":{"content":"hi"},"User[]":[{"name":"a"},{"name":"b"}]}
// after: declare User[] in Request table structure for POST tag Moment, or split into single ops
{"tag":"User","User":{"name":"a"}}
{"tag":"User","User":{"name":"b"}} Defensive patterns
Strategy: validation
Validate before calling
function assertBatchKeysAllowed(requestObj, allowedKeys) {
for (const k of Object.keys(requestObj)) {
if (k.endsWith('[]') && Array.isArray(requestObj[k])
&& !allowedKeys.includes(k)
&& !k.startsWith('@') && !k.endsWith('@')) {
throw new Error(`Undeclared batch key ${k} — add it to the Request table structure or remove it`);
}
}
}
// run before POST/PUT:
assertBatchKeysAllowed(body.Moment, ['User[]']); Type guard
function isDeclaredBatchEntry(k, v, allowed) {
return typeof k === 'string' && Array.isArray(v)
&& k.endsWith('[]') && allowed.has(k);
} Try / catch
try { await apijsonClient.post('/post', body); }
catch (e) {
if (/不允许.*批量操作键值对/.test(e.message)) {
// config gap: surface 'declare Table[] in Request structure' instead of retrying
throw new ConfigError('Batch key not declared for this tag: ' + e.message);
}
throw e;
} Prevention
- Keep the Request table structure in version control and update it in the same commit as any client change adding a Table[] batch key.
- Run a contract test per tag/method: POST the exact production body against a staging backend before release.
- Reuse one shared request-builder module so batch keys are only emitted where the structure declares them.
When it happens
Trigger: A POST/PUT request sends e.g. {"Comment":{...}, "User[]":[{"name":"a"},{"name":"b"}]} where the Request-table 'structure' config for that tag/method has no 'User[]' entry (objKeySet.contains(rk) == false, isArrayKey(rk) == true, rv instanceof List). Any POST/PUT with an undeclared 'Xxx[]':[...] pair inside a verified object triggers it.
Common situations: Developer adds a batch insert to a demo/front-end page but forgets to add the 'User[]':[] placeholder to the Request table structure for that method; using an existing APIJSON front-end (apijson-frontend) against a backend whose Request table was generated by an older script; copy-pasting a batch request into a tag whose structure only allows single-object operations.
Related errors
- 后端 Request 表中 ALLOW_PARTIAL_UPDATE_FAIL:value 中 {key} 不合法!必须
- ${key}: value 中 value 类型错误,只能是 String 或 Map<String, Object>
- ${key}: { ${objKey}: value 中 value 类型错误,只能是 String 或 Map<Str
- JSON 对象格式不正确 !正确示例例如 "User": {}
- 请在最外层传 tag !一般是 Table 名,例如 "tag": "User"
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/9b5a8fa7be413049.
Report an issue: GitHub.