Tencent/APIJSON · error · IllegalArgumentException

${key}: value 中 value 类型错误,只能是 String 或 Map<String, Object>

Error message

${key}: value 中 value 类型错误,只能是 String 或 Map<String, Object> {} !

What it means

Thrown by AbstractParser when parsing a method directive key (@post, @put, @delete, ...) whose top-level value is neither a String nor a Map<String,Object>. The directive value is either a tag string (e.g. "User") or a map of table names to per-table tags/attribute objects; any other JSON type is rejected with IllegalArgumentException.

Source

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

		Object val = request.get(key);
		Map<String, Object> obj = val instanceof Map<?, ?> ? JSON.get(request, key) : null;
		if (obj == null) {
			if (val instanceof String) {
				String[] tbls = StringUtil.split((String) val);
				if (tbls != null && tbls.length > 0) {
					obj = new LinkedHashMap<String, Object>();
					for (String tbl : tbls) {
						if (obj.containsKey(tbl)) {
							throw new ConflictException(key + ": value 中 " + tbl + " 已经存在,不能重复!");
						}

						obj.put(tbl, isPost && isTableArray(tbl)
								? tbl.substring(0, tbl.length() - 2) + ":[]" : "");
					}
				}
			}
			else {
				throw new IllegalArgumentException(key + ": value 中 value 类型错误,只能是 String 或 Map<String, Object> {} !");
			}
		}

		Set<Entry<String, Object>> set = obj == null ? new HashSet<>() : obj.entrySet();
		for (Entry<String, Object> objEntry : set) {
			String objKey = objEntry == null ? null : objEntry.getKey();
			if (objKey == null) {
				continue;
			}

			Map<String, Object> objAttrMap = new HashMap<>();
			objAttrMap.put(KEY_METHOD, keyMethod);
			keyObjectAttributesMap.put(objKey, objAttrMap);

			Object objVal = objEntry.getValue();
			Map<String, Object> objAttrJson = objVal instanceof Map<?, ?> ? JSON.getMap(obj, objKey) : null;
			if (objAttrJson == null) {
				if (objVal instanceof String) {

View on GitHub (pinned to 5284052872)

Solutions

  1. Change the directive value to a plain tag string: "@post": "User"
  2. Or use the map form with String/Map values per table: "@post": {"User": {"tag": "User"}}
  3. If the value comes from client code, log its runtime type before sending and coerce it to a string

Example fix

// before
{"@post": 123, "User": {"name": "a"}}
// after
{"@post": "User", "User": {"name": "a"}}
Defensive patterns

Strategy: validation

Validate before calling

// before sending
const v = req['@post'] ?? req['@put'] ?? req['@delete'];
if (v != null && !(typeof v === 'string' || (typeof v === 'object' && !Array.isArray(v)))) {
  throw new Error('method directive value must be a tag string or an object');
}

Type guard

const isDirectiveValue = v => typeof v === 'string' || (v !== null && typeof v === 'object' && !Array.isArray(v));

Try / catch

try { await client.crud(req); } catch (e) { if (/类型错误,只能是 String 或 Map/.test(e.message)) fixDirectiveType(req); else throw e; }

Prevention

When it happens

Trigger: A batch/CRUD request body containing e.g. "@post": 123, "@post": true, or "@post": ["User"] — the value under the method directive key is a number, boolean, or array instead of "tag" or {"User": "tag"}.

Common situations: Frontend builds the directive value dynamically and accidentally serializes a number or array; copy-paste from docs examples that omit quotes around the tag; JSON produced by a template engine inserting a non-string variable.

Related errors


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