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

  1. 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.
  2. Remove the 'Table[]':[{}] pair from the request and issue one single-object POST/PUT per row instead.
  3. 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).
  4. 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

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


AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14). Data as JSON: /api/errors/9b5a8fa7be413049. Report an issue: GitHub.