Tencent/APIJSON · critical · NullPointerException

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

Error message

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

What it means

Internal NullPointerException from executeAppJoin: the first On has an originKey but getKey() returns null. The key names the main-table column to pull target values from (e.g. userId in "userId@/User/id"); a null key makes the subsequent mainTable.get(on.getTargetKey()) / mapping logic impossible, so execution aborts.

Source

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

				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);
					}
				}

				if (targetValueList.isEmpty() && config.isExplain() == false) {
					throw new NotExistException("targetValueList.isEmpty() && config.isExplain() == false");
				}

View on GitHub (pinned to 5284052872)

Solutions

  1. Provide the full relation including the local column: "MyTable/userId@/User/id".
  2. When constructing On in code, always setKey with the local column name.
  3. Validate joiner strings with a regex like [A-Za-z0-9_$]+/[^/@]+@/[^/@]+/[^/@]+ before use.

Example fix

// before
"join": {"/User/id": "@ APP"}
// after
"join": {"Comment/userId@/User/id": "@ APP"}
Defensive patterns

Strategy: try-catch

Validate before calling

if (on != null && on.getKey() == null) throw new IllegalStateException('APP JOIN On missing local key');

Try / catch

catch (NullPointerException npe) { if (String(npe.getMessage()).contains("Join.onList[0].getKey() = null")) { throw new BadRequestException('join key must include local column before @'); } }

Prevention

When it happens

Trigger: On objects built without setKey, or a joiner string whose key portion before '@' is empty ("/User/id" as the relation segment).

Common situations: Programmatic On construction; malformed joiner strings missing the leading column name; extension code copying On objects field-by-field and skipping key.

Related errors


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