Tencent/APIJSON · error · IllegalArgumentException

joinType + "/.../" + table + "/" + originKey + " 中字符 " + l.g

Error message

joinType + "/.../" + table + "/" + originKey + " 中字符 " + l.getKey() + " 不合法!必须符合字段命名格式!

What it means

Final join-key validation: after stripping operators and the optional '!' logic prefix (new Logic(k)), the bare field name must pass StringUtil.isName — i.e. start with a letter and contain only letters/digits/underscores (a valid identifier). Keys with spaces, dots, dashes, leading digits, or non-ASCII characters throw IllegalArgumentException, because the name will be interpolated into generated SQL as a column identifier.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/Join.java:349

				setRelateType("<");
				k = originKey.substring(0, originKey.length() - 1);
			}
			else {
				setRelateType("");
				k = originKey;
			}

			if (k != null && (k.contains("&") || k.contains("|"))) {
				throw new UnsupportedOperationException(joinType + "/.../" + table + "/" + originKey + " 中字符 " + k + " 不合法!与或非逻辑符仅支持 '!' 非逻辑符 !");
			}

			//TODO if (c3 == '-') { // 表示 key 和 value 顺序反过来: value LIKE key

			Logic l = new Logic(k);
			setLogic(l);

			if (StringUtil.isName(l.getKey()) == false) {
				throw new IllegalArgumentException(joinType + "/.../" + table + "/" + originKey + " 中字符 " + l.getKey() + " 不合法!必须符合字段命名格式!");
			}

			setKey(l.getKey());
		}

  }

}

View on GitHub (pinned to 5284052872)

Solutions

  1. Use plain identifiers in join keys: letters, digits, underscore, starting with a letter — e.g. "userId@":"/Moment/userId".
  2. Move qualifying prefixes into the reference path (the '/table/field@' part), not the key: "id@":"/Moment/userId".
  3. If the actual DB column contains special chars, alias it in the structure config (@column) rather than in the join key; sanitize any programmatically generated keys with a ^[A-Za-z][A-Za-z0-9_]*$ check.

Example fix

// before
"User":{"user.id@":"/Moment/userId"}
// after
"User":{"id@":"/Moment/userId"}
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern NAME = Pattern.compile("^[A-Za-z][A-Za-z0-9_]*$");
String bareKeyAfterOperators(String k) { return k.replaceFirst("(\\{\\}|\\[\\]|<>|\\$|\\*?~|>=|<=|>|<|!)", ""); }
void assertJoinKeyIsName(String k) {
  String bare = bareKeyAfterOperators(k);
  if (!NAME.matcher(bare).matches())
    throw new IllegalArgumentException("join key '" + k + "' reduces to '" + bare + "' which is not a valid identifier");
}

Type guard

function isJoinKeyName(k) { return /^[A-Za-z][A-Za-z0-9_]*$/.test(k.replace(/[\{\}\[\]<>$~%_?>=!*]+$/, '')); }

Prevention

When it happens

Trigger: A join reference key like "user.id@" (dot), "my-name@" (dash), "1id@" (leading digit), or "名字@" (non-ASCII) after operator stripping leaves l.getKey() failing StringUtil.isName, e.g. from ORM joins. Also fires when only operators remain (empty key after stripping) or a key consists solely of placeholders.

Common situations: Using JSON-path style 'user.id' in join keys; column aliases with dashes leaking into keys; generating join config from user input without identifier validation; using SQL-quoted identifiers ("`col`") in key names.

Related errors


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