Tencent/APIJSON · error · IllegalArgumentException

join:value 中 value 的 alias 值 ${alias} 不合法!必须为 &/Table0,</Tab

Error message

join:value 中 value 的 alias 值 ${alias} 不合法!必须为 &/Table0,</Table1/key1,@/Table1:alias2/key2,... 或 { '&/Table0':{}, '</Table1/key1':{},... } 这种格式!且 Table:alias 的 alias 必须满足英文单词变量名格式!

What it means

If a join path carries Table:alias, the alias is validated with StringUtil.isName (non-empty case): it must be a plain identifier word. An alias containing symbols, slashes, brackets, or starting with a digit throws IllegalArgumentException with the grammar reminder.

Source

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

			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 必须满足英文单词变量名格式!");
			}

			// 取出Table对应的JSONObject,及内部引用赋值 key:value
			M tableObj;
			M parentPathObj;	// 保留
			try {
				parentPathObj = arrKey == null ? request : JSON.get(request, arrKey);	// 保留
				tableObj = parentPathObj == null ? null : JSON.get(parentPathObj, tableKey);
				if (tableObj == null) {
					throw new NullPointerException("tableObj == null");
				}
			}
			catch (Exception e2) {
				throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 对应的 " + tableKey + ":value 中 value 类型不合法!" +
          			"必须是 {} 这种 Map<String, Object> 格式!" + e2.getMessage());
			}

View on GitHub (pinned to 5284052872)

Solutions

  1. Keep the alias a bare identifier: '&/User:owner'
  2. Use the alias only for disambiguation between multiple joins of the same table
  3. Put join conditions inside the table object, not in the alias
  4. Sanitize any dynamic alias to [A-Za-z_][A-Za-z0-9_]* before sending

Example fix

// before
{"@join":"&/User:owner-2/id"}
// after
{"@join":"&/User:owner2/id"}
Defensive patterns

Strategy: validation

Validate before calling

if (alias != null && !alias.matches("^[A-Za-z_][A-Za-z0-9_]*$")) throw new IllegalArgumentException("bad join alias: " + alias);

Type guard

boolean isValidJoinAlias(String a) { return a == null || a.matches("^[A-Za-z_][A-Za-z0-9_]*$"); }

Prevention

When it happens

Trigger: "@join":"&/User:owner-2", '@/User:a.b', or '&/User:owner/toId' where the slash makes the alias segment parse into invalid parts. Any non-identifier alias text.

Common situations: Using quoted or spaced aliases; trying to express join ON-conditions in the alias slot; concatenating user input into the alias; thinking alias may include dots for schema qualification.

Related errors


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