Tencent/APIJSON · error · IllegalArgumentException

预编译模式下 @partition:value 中 ${item} 不合法! value 里面用 , 分割的每一项必须是

Error message

预编译模式下 @partition:value 中 ${item} 不合法! value 里面用 , 分割的每一项必须是 column 且其中 column 必须是 英语单词!并且不要有多余的空格!

What it means

Prepared-mode validation of @partition:value: each comma-separated item must be a single-word identifier (StringUtil.isName). PARTITION BY items are inlined into SQL, so only clean names are accepted.

Source

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

				}
			}
		}

		String partition = StringUtil.trim(getPartition());

		String[] keys = StringUtil.split(partition);
		if (keys == null || keys.length <= 0) {
			return StringUtil.isEmpty(joinPartition, true) ? "" : (hasPrefix ? " PARTITION BY " : "") + joinPartition;
		}

		for (int i = 0; i < keys.length; i++) {
			String item = keys[i];
			String origin = item;

			if (isPrepared()) { //不能通过 ? 来代替,SELECT 'id','name' 返回的就是 id:"id", name:"name",而不是数据库里的值!
				//这里既不对origin trim,也不对 ASC/DESC ignoreCase,希望前端严格传没有任何空格的字符串过来,减少传输数据量,节约服务器性能
				if (StringUtil.isName(origin) == false) {
					throw new IllegalArgumentException("预编译模式下 @partition:value 中 " + item + " 不合法! value 里面用 , 分割的"
							+ "每一项必须是 column 且其中 column 必须是 英语单词!并且不要有多余的空格!");
				}
			}

			keys[i] = gainKey(origin);
		}

		return (hasPrefix ? " PARTITION BY " : "") + StringUtil.concat(StringUtil.get(keys), joinPartition, ", ");
	}

	@Override
	public String getFill() {
		return fill;
	}
	public AbstractSQLConfig<T, M, L> setFill(String... conditions) {
		return setFill(StringUtil.get(conditions));
	}
	@Override

View on GitHub (pinned to 5284052872)

Solutions

  1. Pass plain partition column names: "@partition": "eventDate"
  2. Put function expressions in RAW_MAP and reference them with @raw
  3. Check for stray spaces after commas before sending

Example fix

// before
{"@partition": "toYYYYMM(created_at)"}
// after
{"@raw": "@partition", "@partition": "ymPartition"}  // ymPartition -> toYYYYMM(created_at) in backend RAW_MAP
Defensive patterns

Strategy: validation

Validate before calling

for (const item of String(obj['@partition'] ?? '').split(',')) {
  if (item && !/^[A-Za-z_][A-Za-z0-9_]*$/.test(item)) throw new Error(`@partition item '${item}' must be a single word; use @raw for expressions`);
}

Type guard

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

Try / catch

try { await api.get(req); } catch (e) { if (e.message.includes('@partition')) convertPartitionToRawToken(req); else throw e; }

Prevention

When it happens

Trigger: "@partition": "toYYYYMM(created_at)" (function call), "@partition": "part key" — any item that is not one identifier word.

Common situations: ClickHouse-style partition expressions pasted verbatim; expecting @partition to accept functions like @column does; multi-word identifiers.

Related errors


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