Tencent/APIJSON · error · IllegalArgumentException

截至 ${config.getTable()} 已执行 ${sqlCount} 条 SQL,数量已超限,必须在 0-${

Error message

截至 ${config.getTable()} 已执行 ${sqlCount} 条 SQL,数量已超限,必须在 0-${maxSQLCount} 内 !

What it means

After executing the top-level request item (config.getPosition() == 0), the parser counts SQL statements executed by the SQL executor and compares against getMaxSQLCount(). If exceeded, an IllegalArgumentException is thrown from the finally block — a guard against runaway queries from deep joins, huge batches, or recursive APP JOIN fan-out.

Source

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

			}
			else {
				result = getSQLExecutor().execute(config, false);
				// FIXME 改为直接在 sqlExecutor 内加好,最后 Parser<T, M, L> 取结果,可以解决并发执行导致内部计算出错
//				executedSQLDuration += sqlExecutor.getExecutedSQLDuration() + sqlExecutor.getSqlResultDuration();
			}

			return result;
		}
		catch (Exception e) {
			throw CommonException.wrap(e, config);
		}
		finally {
			if (config.getPosition() == 0 && config.limitSQLCount()) {
				int maxSQLCount = getMaxSQLCount();
				int sqlCount = getSQLExecutor().getExecutedSQLCount();
				Log.d(TAG, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< \n\n\n 已执行 " + sqlCount + "/" + maxSQLCount + " 条 SQL \n\n\n >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
				if (sqlCount > maxSQLCount) {
					throw new IllegalArgumentException("截至 " + config.getTable() + " 已执行 " + sqlCount + " 条 SQL,数量已超限,必须在 0-" + maxSQLCount + " 内 !");
				}
			}
		}
	}


	//事务处理 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
	private int transactionIsolation = Connection.TRANSACTION_NONE;
	@Override
	public int getTransactionIsolation() {
		return transactionIsolation;
	}
	@Override
	public void setTransactionIsolation(int transactionIsolation) {
		this.transactionIsolation = transactionIsolation;
	}

	@Override

View on GitHub (pinned to 5284052872)

Solutions

  1. Reduce the SQL fan-out: shrink 'count'/batch size, unnest arrays, or replace APP JOIN per-row lookups with SQL JOIN
  2. Raise the cap deliberately via your parser configuration (override getMaxSQLCount()/setMaxSQLCount on the Parser, or the corresponding framework config) after assessing DB load
  3. Split one mega-request into several smaller requests so each stays under the limit

Example fix

// before
{ '[]': { 'count': 500, 'User': {}, 'join': '@/User/Comment/toId@' } }  // one SQL per user -> blows past maxSQLCount
// after
{ '[]': { 'count': 20, 'User': {}, 'join': '</Comment/userId@', 'Comment': { 'userId@': '/User/id' } } }  // single JOIN SQL
Defensive patterns

Strategy: try-catch

Validate before calling

// Estimate SQL cost client-side before sending: parent rows x per-row APP JOIN tables + 1 per SQL-joined table + 1 per array level
function estimateSQLCount(req) {
  let n = 0;
  for (const [k, v] of Object.entries(req)) {
    if (k.endsWith('[]') && v && typeof v === 'object') {
      n += 1 + (v.count ?? 10) * countAppJoinTables(v); // rough upper bound
    } else if (v && typeof v === 'object') n += 1;
  }
  return n;
}
// if (estimateSQLCount(req) > MAX_SQL_COUNT) shrink count / batch before sending

Try / catch

try { result = parser.parse(request); } catch (IllegalArgumentException e) { if (e.getMessage().contains('数量已超限')) { /* halve batch size and retry once, or surface quota error to caller */ } else throw e; }

Prevention

When it happens

Trigger: A single request whose joins/arrays fan out into more SQL statements than the limit (default caps are small, e.g. 200): batch inserts of many rows, APP JOIN over a large parent array (one SQL per parent row), nested multi-level arrays, or @combine with many conditions.

Common situations: Raising batch sizes without adjusting limits; enabling APP JOIN on lists that previously used SQL JOIN; production data growth pushing a per-row lookup pattern past the cap; demo defaults left in place.

Related errors


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