Tencent/APIJSON · error · IllegalArgumentException

join:'${e.getKey()}' 中 ${k} 不合法 !@ APP JOIN 只允许 key@:/Table/

Error message

join:'${e.getKey()}' 中 ${k} 不合法 !@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!

What it means

Same identifier rule as the explicit-key variant, but applied to keys discovered while scanning the joined table object for APP JOIN: the candidate key 'k' minus its trailing '@' must pass StringUtil.isName. If it does not, this IllegalArgumentException is thrown because '@' joins only permit key@:/Table/refKey '=' connections.

Source

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

				if (k.length() > 1 && k.indexOf("@") == k.length() - 1 && v instanceof String) {
					String sv = (String) v;
					int ind = sv.endsWith("@") ? -1 : sv.indexOf("/");
					if (ind == 0 && key == null) {  // 指定了某个就只允许一个 ON 条件
						String p = sv.substring(1);
						int ind2 = p.indexOf("/");
						String tk = ind2 < 0 ? null : p.substring(0, ind2);

						apijson.orm.Entry<String, String> te = tk == null || p.substring(ind2 + 1).indexOf("/") >= 0 ? null : Pair.parseEntry(tk, true);

						if (te != null && isTableKey(te.getKey()) && request.get(tk) instanceof Map<?, ?>) {
							if (isAppJoin) {
								if (refObj.size() >= 1) {
									throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":" + e.getKey() + " 中 " + k + " 不合法!"
											+ "@ APP JOIN 必须有且只有一个引用赋值键值对!");
								}

								if (StringUtil.isName(k.substring(0, k.length() - 1)) == false) {
									throw new IllegalArgumentException(apijson.JSONRequest.KEY_JOIN + ":'" + e.getKey() + "' 中 " + k + " 不合法 !" +
											"@ APP JOIN 只允许 key@:/Table/refKey 这种 = 等价连接!");
								}
							}

							refObj.put(k, v);
							continue;
						}
					}

					Object rv = getValueByPath(sv);
					if (rv != null && rv.equals(sv) == false) {
						requestObj.put(k.substring(0, k.length() - 1), rv);
						continue;
					}

					throw new UnsupportedOperationException(table + "/" + k + " 不合法!" + apijson.JSONRequest.KEY_JOIN + " 关联的 Table 中,"
							+ "join: ?/Table/key 时只能有 1 个 key@:value;join: ?/Table 时所有 key@:value 要么是符合 join 格式,要么能直接解析成具体值!");  // TODO 支持 join on
				}

View on GitHub (pinned to 5284052872)

Solutions

  1. Rename the reference key to a valid identifier (letter first, then letters/digits/underscore): 'user-id@' -> 'userId@'
  2. Keep the key and value consistent: the same key must be the single ON condition of the '@' join

Example fix

// before
{ 'join': '@/Comment', 'Comment': { 'user-id@': '/User/id' } }
// after
{ 'join': '@/Comment', 'Comment': { 'userId@': '/User/id' } }
Defensive patterns

Strategy: validation

Validate before calling

const NAME_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
function checkRefKeys(joinValue) {
  const paths = typeof joinValue === 'string' ? [joinValue] : Object.keys(joinValue);
  for (const p of paths.filter(x => x.startsWith('@'))) {
    const tblKey = p.split('/')[1];
    // caller checks req[tblKey] keys:
  }
  return null;
}
// apply to table object: Object.keys(tbl).filter(k => k.endsWith('@')).every(k => NAME_RE.test(k.slice(0, -1)))

Type guard

const isValidRefKey = (k) => /^[A-Za-z_][A-Za-z0-9_]*@$/.test(k);

Try / catch

Catch IllegalArgumentException with 'APP JOIN 只允许 key@:/Table/refKey'; surface which key failed (named in message).

Prevention

When it happens

Trigger: { 'join': '@/Comment', 'Comment': { 'user-id@': '/User/id' } } — the reference key 'user-id@' has a hyphen in its name part; likewise keys starting with a digit, containing spaces, '@', or other punctuation.

Common situations: Auto-generating request keys from DB column names that contain hyphens; mixing camelCase and kebab-case during refactor; a template engine emitting malformed key names.

Related errors


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