Tencent/APIJSON · error · IllegalArgumentException

请在最外层传 tag !一般是 Table 名,例如 "tag": "User"

Error message

请在最外层传 tag !一般是 Table 名,例如 "tag": "User" 

What it means

buildTag() requires a top-level "tag" for non-CRUD operations when the object itself carries no tag. The tag (usually the table name) selects which request structure/permission template the verifier applies; without it verification cannot proceed.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractParser.java:2577

	protected void setRequestAttribute(String key, boolean isArray, String attrKey, @NotNull Map<String, Object> request) {
		Map<String, Object> attrMap = keyObjectAttributesMap.get(isArray ? key + KEY_ARRAY : key);
		Object attrVal = attrMap == null ? null : attrMap.get(attrKey);
		Map<String, Object> obj = attrVal == null ? null : JSON.get(request, key);

		if (obj != null && obj.get(attrKey) == null) {
			// 如果对象内部已经包含该属性,不覆盖
			obj.put(attrKey, attrVal);
		}
	}

	protected String buildTag(Map<String, Object> request, String key, RequestMethod method, String tag) {
		if (method == RequestMethod.CRUD) {
			Map<String, Object> attrMap = keyObjectAttributesMap.get(key);
			Object _tag = attrMap == null ? null : attrMap.get(KEY_TAG);
			return _tag != null ? _tag.toString() : StringUtil.isEmpty(tag) ? key : tag;
		} else {
			if (StringUtil.isEmpty(tag, true)) {
				throw new IllegalArgumentException("请在最外层传 tag !一般是 Table 名,例如 \"tag\": \"User\" ");
			}
		}
		return tag;
	}


	protected M objectVerify(RequestMethod method, String tag, int version, String name, @NotNull M request
			, int maxUpdateCount, SQLCreator<T, M, L> creator, M object) throws Exception {
		// 获取指定的JSON结构 >>>>>>>>>>>>>>
		M target = wrapRequest(method, tag, object, true);
		// Map<String, Object> clone 浅拷贝没用,Structure.parse 会导致 structure 里面被清空,第二次从缓存里取到的就是 {}
		return getVerifier().setParser(this).verifyRequest(method, name, target, request, maxUpdateCount
				, getGlobalDatabase(), getGlobalDatasource(), getGlobalNamespace(), getGlobalCatalog(), getGlobalSchema()
		);
	}

	/***
	 * 兼容url crud, 获取真实method

View on GitHub (pinned to 5284052872)

Solutions

  1. Add a top-level tag equal to the table: {"tag": "User", "User": {...}}
  2. Or set a per-object tag via the method directive map: "@put": {"User": "User"}
  3. Centralize tag emission in the client's request builder so every write request carries it

Example fix

// before
POST /put  {"User": {"id": 1, "name": "a"}}
// after
POST /put  {"tag": "User", "User": {"id": 1, "name": "a"}}
Defensive patterns

Strategy: validation

Validate before calling

if (method !== 'CRUD' && (req.tag == null || String(req.tag).trim() === '')) {
  req.tag = Object.keys(req).find(k => !k.startsWith('@')) ?? null;
  if (!req.tag) throw new Error('non-CRUD request needs a top-level tag, e.g. "tag":"User"');
}

Type guard

const hasTag = req => typeof req?.tag === 'string' && req.tag.trim().length > 0;

Try / catch

try { await client.put(req); } catch (e) { if (e.message.includes('请在最外层传 tag')) { req.tag = deriveTagFromTable(req); return client.put(req); } throw e; }

Prevention

When it happens

Trigger: Calling /put, /delete or another non-CRUD batch endpoint with a body that has no "tag": "User" at the top level and no per-object tag provided via the method directive map.

Common situations: Migrating single-object requests to batch style and forgetting the tag; frontend builds the body from form data that never included tag; tag key removed during a refactor.

Related errors


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