Tencent/APIJSON · error · IllegalAccessException

没权限访问或对象不存在!

Error message

没权限访问或对象不存在!

What it means

Thrown as IllegalAccessException by AbstractSQLExecutor after a PUT/DELETE statement executes and updateCount <= 0. Zero affected rows means no row matched the WHERE conditions, which for writes is indistinguishable from 'no permission for that object' — so the request fails instead of returning success (the comment notes a NotExist-like success conversion must not happen here).

Source

Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java:242

				//导致后面 rs.getMetaData() 报错 Operation not allowed after ResultSet closed		result.put("moreResults", statement.getMoreResults());
			}
			else {
				RequestMethod method = config.getMethod();
				switch (method) {
				case POST:
				case PUT:
				case DELETE:
					if (isExplain == false) { //只有 SELECT 才能 EXPLAIN
						executedSQLCount ++;
						executedSQLStartTime = System.currentTimeMillis();
					}
					int updateCount = executeUpdate(config);
					if (isExplain == false) {
						executedSQLDuration += System.currentTimeMillis() - executedSQLStartTime;
					}

					if (updateCount <= 0) {
						throw new IllegalAccessException("没权限访问或对象不存在!");  // NotExistException 会被 catch 转为成功状态
					}

					// updateCount>0时收集结果。例如更新操作成功时,返回count(affected rows)、id字段
					result = parser.newSuccessResult();  // TODO 对 APIAuto 及其它现有的前端/客户端影响比较大,暂时还是返回 code 和 msg,5.0 再移除  JSON.createJSONObject();

					//id,id{}至少一个会有,一定会返回,不用抛异常来阻止关联写操作时前面错误导致后面无条件执行!
					result.put(JSONResponse.KEY_COUNT, updateCount);//返回修改的记录数

					String idKey = config.getIdKey();
					if (config.getId() != null) {
						result.put(idKey, config.getId());
					}
					if (config.getIdIn() != null) {
						result.put(idKey + "[]", config.getIdIn());
					}

					if (method == RequestMethod.PUT || method == RequestMethod.DELETE) {
						config.setMethod(RequestMethod.GET);

View on GitHub (pinned to 5284052872)

Solutions

  1. Re-check that the target row exists (e.g. a prior GET with the same conditions/permissions) before retrying the write.
  2. Prefer addressing rows by primary key (id) rather than by mutable column values.
  3. Handle the 404-ish outcome in the client: treat as 'already deleted / no permission' and reconcile UI state instead of blindly retrying.
  4. If permission rules are the cause, adjust the request session/role or the access model for that table.

Example fix

// before
{"User": {"id": 123, "name": "old"}}  // name already changed by someone else
// after
{"User": {"id": 123}}
Defensive patterns

Strategy: try-catch

Validate before calling

const r = await apijson.get({ [table]: { id } });
if (!r[table] || Object.keys(r[table]).length === 0) throw new NotFoundError(`${table}#${id}`);
await apijson.put({ [table]: { id, ...changes } });

Try / catch

try {
  await apijson.put(body);
} catch (e) {
  if (e instanceof IllegalAccessException || /没权限访问或对象不存在/.test(e.message)) {
    // row gone or not yours: reconcile UI, do not blind-retry
    return { ok: false, reason: 'gone-or-forbidden' };
  }
  throw e;
}

Prevention

When it happens

Trigger: PUT/DELETE where the id/condition matches nothing: record already deleted, wrong id, condition on a column value that changed, or row-level permission filtering that rewrites the WHERE to match nothing.

Common situations: Concurrent deletes (double submit), stale client data after another user's update, permission (visitor vs own data) rules excluding the row, or weak conditions like name-based matching.

Related errors


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