Tencent/APIJSON · critical · NullPointerException

服务器内部错误,List<Join> 中 Join.onList[0].getOriginKey() = null!

Error message

服务器内部错误,List<Join> 中 Join.onList[0].getOriginKey() = null!

What it means

Internal NullPointerException from executeAppJoin: the first On of an APP JOIN exists but getOriginKey() returns null. originKey (the "key@/Table/key" string) is required to know which vice-table column maps to the main table; without it the APP JOIN data-caching step cannot proceed.

Source

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

					Log.i(TAG, "executeAppJoin  for (Join j : joinList) >> j.isAppJoin() == false >>  continue;");
					continue;
				}

				SQLConfig<T, M, L> cc = join.getCacheConfig(); //这里用config改了getSQL后再还原很麻烦,所以提前给一个config2更好
				if (cc == null) {
					if (Log.DEBUG) {
						throw new NullPointerException("服务器内部错误, executeAppJoin cc == null ! 导致不能缓存 @ APP JOIN 的副表数据!");
					}
					continue;
				}

				SQLConfig<T, M, L> jc = join.getJoinConfig();

				List<On> onList = join.getOnList();
				On on = onList == null || onList.isEmpty() ? null : onList.get(0);  // APP JOIN 应该有且只有一个 ON 条件
				String originKey = on == null ? null : on.getOriginKey();
				if (originKey == null) {
					throw new NullPointerException("服务器内部错误,List<Join> 中 Join.onList[0" + (on == null ? "] = null!" : ".getOriginKey() = null!"));
				}
				String key = on.getKey();
				if (key == null) {
					throw new NullPointerException("服务器内部错误,List<Join> 中 Join.onList[0" + (on == null ? "] = null!" : ".getKey() = null!"));
				}

				// 取出 "id@": "@/User/userId" 中所有 userId 的值
				List<Object> targetValueList = new ArrayList<>();

				for (int i = 0; i < resultList.size(); i++) {
					M mainTable = resultList.get(i);
					Object targetValue = mainTable == null ? null : mainTable.get(on.getTargetKey());

					if (targetValue != null && targetValueList.contains(targetValue) == false) {
						targetValueList.add(targetValue);
					}
				}

View on GitHub (pinned to 5284052872)

Solutions

  1. Set originKey on the On used for APP JOIN (full "key@/Target/key" string).
  2. Prefer letting APIJSON parse the joiner string rather than building On manually.
  3. Align jar versions; report with the request body if input is standard.

Example fix

// before
On on = new On(); on.setKey("userId"); on.setTargetKey("id");
// after
On on = new On(); on.setKey("userId"); on.setTargetKey("id"); on.setOriginKey("userId@/User/id");
Defensive patterns

Strategy: try-catch

Try / catch

catch (NullPointerException npe) { if (String(npe.getMessage()).contains("Join.onList[0].getOriginKey() = null")) { // rebuild On with full originKey 'key@/Table/key' } }

Prevention

When it happens

Trigger: An On object present in onList but constructed without originKey — typically programmatic Join/On creation or a parsing path that set key/targetTableKey but not originKey.

Common situations: Custom code extending APIJSON that builds On via setters and skips setOriginKey; migration between versions where the On model changed.

Related errors


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