Tencent/APIJSON · error · IllegalArgumentException

@join:'{}' 对应的 {} 不是合法的数组 key[] !@ APP JOIN 最多允许跨 1 层,只能是子数组

Error message

@join:'{}' 对应的 {} 不是合法的数组 key[] !@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!

What it means

When a join path contains a middle segment between the type sigil and the table (arrKey, e.g. 'list[]' in '@/list[]/User'), that segment is validated with isArrayKey(): it must literally end with '[]'. A non-array middle segment throws IllegalArgumentException; the message mentions @ APP JOIN because spanning into a sub-array is the @-join feature, limited to one level, with no join key allowed inside the sub-array object.

Source

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

			}

			int index = path == null ? -1 : path.indexOf("/");
			if (index < 0) {
				throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":value 中 value 值 " + path + " 不合法!"
						+ "必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种形式!");
			}
			String joinType = path.substring(0, index); //& | ! < > ( ) <> () *
			//			if (StringUtil.isEmpty(joinType, true)) {
			//				joinType = "|"; // FULL JOIN
			//			}
			path = path.substring(index + 1);

			index = path.lastIndexOf("/");
			String tableKey = index < 0 ? path : path.substring(0, index); // User:owner
			int index2 = tableKey.lastIndexOf("/");
			String arrKey = index2 < 0 ? null : tableKey.substring(0, index2);
			if (arrKey != null && isArrayKey(arrKey) == false) {
				throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + arrKey + " 不是合法的数组 key[] !" +
						"@ APP JOIN 最多允许跨 1 层,只能是子数组,且数组对象中不能有 join: value 键值对!");
			}

			tableKey = index2 < 0 ? tableKey : tableKey.substring(index2+1);

			apijson.orm.Entry<String, String> entry = Pair.parseEntry(tableKey, true);
			String table = entry.getKey(); // User
			if (StringUtil.isName(table) == false) {
				throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":value 中 value 的 Table 值 " + table + " 不合法!"
						+ "必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式!"
						+ "且 Table 必须满足大写字母开头的表对象英文单词 key 格式!");
			}

			String alias = entry.getValue(); // owner
			if (StringUtil.isNotEmpty(alias, true) && StringUtil.isName(alias) == false) {
				throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":value 中 value 的 alias 值 " + alias + " 不合法!"
						+ "必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式!"
						+ "且 Table:alias 的 alias 必须满足英文单词变量名格式!");

View on GitHub (pinned to 5284052872)

Solutions

  1. Use SQL joins (& < > etc.) instead of @ APP JOIN for cross-level linking — they are not depth-limited this way
  2. Flatten the request so the app-joined table sits directly inside one array level: '@/list[]/User'
  3. Ensure the middle segment literally ends with '[]' (isArrayKey check)
  4. Do not put a join key inside the sub-array object (see companion error)

Example fix

// before
{"@join":"@/a[]/b[]/User","a[]":{"b[]":{"User":{}}}}
// after
{"@join":"&/User/id","a[]":{"b[]":{"User":{"id@":"..."}}}}
Defensive patterns

Strategy: validation

Validate before calling

String middle = pathBetweenSigilAndTable(p);
if (middle != null && !middle.endsWith("[]")) throw new IllegalArgumentException("@ join middle key must be array key[]");

Type guard

boolean isArrayKey(String k) { return k != null && k.endsWith("[]"); }

Prevention

When it happens

Trigger: "@join":"@/a[]/b[]/User" (two array levels), or '@/someObj/User/id' where someObj is a plain object not ending in []. Any join whose path has two slashes hits the arrKey check.

Common situations: Deep nested comment trees with app-join on both levels; using APP JOIN where SQL JOIN works fine; forgetting that the target must be a key[] array object inside the current request.

Related errors


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