Tencent/APIJSON · error · UnsupportedOperationException

字符串 ${expression} 不合法!预编译模式下 @having:"column?value;function(

Error message

字符串 ${expression} 不合法!预编译模式下 @having:"column?value;function(arg0,arg1,...)?value..." 中 column?value 必须符合正则表达式 ${PATTERN_FUNCTION} 且不包含连续减号 -- !不允许空格!

What it means

In prepared mode, a @having expression without parentheses must fully match PATTERN_FUNCTION (the column?value form). No spaces, no consecutive dashes --, only the whitelisted operator/comparison shape. This is the primary injection guard for HAVING since values cannot be bound parameters inside expressions.

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLConfig.java:1768

	protected String gainHavingItem(String quote, String table, String alias
			, String key, String expression, boolean containRaw) throws Exception {
		//fun(arg0,arg1,...)
		if (containRaw) {
			String rawSQL = gainRawSQL(KEY_HAVING, expression);
			if (rawSQL != null) {
				return rawSQL;
			}
		}

		if (expression.length() > 100) {
			throw new UnsupportedOperationException("@having:value 的 value 中字符串 " + expression + " 不合法!"
					+ "不允许传超过 100 个字符的函数或表达式!请用 @raw 简化传参!");
		}

		int start = expression.indexOf("(");
		if (start < 0) {
			if (isPrepared() && PATTERN_FUNCTION.matcher(expression).matches() == false) {
				throw new UnsupportedOperationException("字符串 " + expression + " 不合法!"
						+ "预编译模式下 @having:\"column?value;function(arg0,arg1,...)?value...\""
						+ " 中 column?value 必须符合正则表达式 " + PATTERN_FUNCTION + " 且不包含连续减号 -- !不允许空格!");
			}
			
			return parseSQLExpression(KEY_HAVING, expression, containRaw, false, null);
		}

		int end = expression.lastIndexOf(")");
		if (start >= end) {
			throw new IllegalArgumentException("字符 " + expression + " 不合法!"
					+ "@having:value 中 value 里的 SQL函数必须为 function(arg0,arg1,...) 这种格式!");
		}

		String method = expression.substring(0, start);
		if (method.isEmpty() == false) {
			if (SQL_FUNCTION_MAP == null || SQL_FUNCTION_MAP.isEmpty()) {
				if (StringUtil.isName(method) == false) {
					throw new IllegalArgumentException("字符 " + method + " 不合法!"

View on GitHub (pinned to 5284052872)

Solutions

  1. Remove all spaces: "@having": "amount>0"
  2. Use the supported key(condition) form and APIJSON operators instead of raw SQL keywords
  3. For legitimately complex expressions use @raw + server-side RAW_MAP

Example fix

// before
{"@having": "amount > 0"}
// after
{"@having": "amount>0"}
Defensive patterns

Strategy: validation

Validate before calling

// mirror of the server check for the no-paren form: no spaces, no '--'
const okSimple = s => /^[A-Za-z0-9_.]+(>=|<=|>|<|!=|=)[^\s'\-]*$/.test(s) && !s.includes('--');
const hv = obj['@having'];
if (typeof hv === 'string' && !hv.includes('(') && !okSimple(hv)) {
  throw new Error(`@having '${hv}' fails column?value pattern (no spaces, no --)`);
}

Type guard

const isSimpleHavingValid = s => typeof s === 'string' && !/\s/.test(s) && !s.includes('--');

Try / catch

try { await api.get(req); } catch (e) { if (e.message.includes('PATTERN_FUNCTION')) req['User']['@having'] = req['User']['@having'].replace(/\s+/g, ''); else throw e; }

Prevention

When it happens

Trigger: "@having": "amount > 0" (spaces), "@having": "a--b>1" (double dash), "@having": "name='x' or 1=1" — any parentheses-free expression that fails the regex.

Common situations: Pretty-printed JSON with spaces inside the value; frontend template inserting user text unescaped; trying SQL syntax (OR, quotes) that the pattern intentionally forbids.

Related errors


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