Tencent/APIJSON · error · IllegalArgumentException

originKey + ":value 中字符 " + originKey + " 不合法!key$:value 中不允

Error message

originKey + ":value 中字符 " + originKey + " 不合法!key$:value 中不允许只有单独的 '?',必须和 '%', '_' 之一配合使用 !

What it means

In the same '$' (LIKE) placeholder parsing: '?' means 'use the value as-is at this position' and only makes sense combined with '%' or '_' (key?%$ → LIKE 'v%', key_?$ → LIKE '_v'). A key ending with just '?$', i.e. a lone '?' with no % or _ companion, throws IllegalArgumentException because '?value' alone would produce a malformed/pointless LIKE pattern.

Source

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

				k = originKey.substring(0, originKey.length() - 1);
				char c = k.isEmpty() ? 0 : k.charAt(k.length() - 1);

				String t = "$";
				if (c == '%' || c == '_' || c == '?') {
					t = c + t;
					k = k.substring(0, k.length() - 1);

					char c2 = k.isEmpty() ? 0 : k.charAt(k.length() - 1);
					if (c2 == '%' || c2 == '_' || c2 == '?') {
						if (c2 == c) {
							throw new IllegalArgumentException(originKey + ":value 中字符 " + k + " 不合法!key$:value 中不允许 key 中有连续相同的占位符!");
						}

						t = c2 + t;
						k = k.substring(0, k.length() - 1);
					}
					else if (c == '?') {
						throw new IllegalArgumentException(originKey + ":value 中字符 " + originKey + " 不合法!key$:value 中不允许只有单独的 '?',必须和 '%', '_' 之一配合使用 !");
					}
				}

				setRelateType(t);
			}
			else if (originKey.endsWith("~")) {
				boolean ignoreCase = originKey.endsWith("*~");
				setRelateType(ignoreCase ? "*~" : "~");
				k = originKey.substring(0, originKey.length() - (ignoreCase ? 2 : 1));
			}
			else if (originKey.endsWith(">=")) {
				setRelateType(">=");
				k = originKey.substring(0, originKey.length() - 2);
			}
			else if (originKey.endsWith("<=")) {
				setRelateType("<=");
				k = originKey.substring(0, originKey.length() - 2);
			}

View on GitHub (pinned to 5284052872)

Solutions

  1. Use the default containment form with no placeholder: "name$":"a" → LIKE '%a%'.
  2. Combine '?' with % or _: "name?%$":"a" → LIKE 'a%', "name_?$":"a" → LIKE '_a'.
  3. For a literal '?' in a pattern, include it in the value string instead of the key.

Example fix

// before
"User":{"name?$":"Tom"}   // lone '?', rejected
// after
"User":{"name$":"Tom"}    // LIKE '%Tom%'
// or
"User":{"name?%$":"Tom"} // LIKE 'Tom%'
Defensive patterns

Strategy: validation

Validate before calling

function assertLikeJoinKey(k) {
  if (/[?]\$$/.test(k) && !/[%_][?]\$$|[?][%_]\$$/.test(k))
    throw new Error("lone '?' in '" + k + "' — combine with % or _ (key?%$, key_?$) or drop it (key$)");
}

Type guard

function isLikeJoinKey(k) { return !/\?\$$/.test(k) || /[%_]\?\$|\?[%_]\$/.test(k); }

Prevention

When it happens

Trigger: Join table object contains e.g. "name?$":"a" or "status?$":"x" — after stripping the trailing '?', the next char back is neither '%', '_', nor '?' (c == '?' and no c2 companion), so the else-if branch throws.

Common situations: Assuming '?' is a single-char wildcard like SQL '_' — in APIJSON '?' is an exact-position marker, not a wildcard; typo when aiming for 'key_?$'; forgetting that plain containment already is the default (key$ → LIKE '%v%') so no placeholder is needed at all.

Related errors


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