Tencent/APIJSON · critical · NullPointerException
服务器内部错误,List<Join> 中 Join.onList[{}] = null!
Error message
服务器内部错误,List<Join> 中 Join.onList[{}] = null! What it means
Internal NullPointerException from the JOIN-cache loop in the SQL executor: while back-filling vice-table cache configs from join ON conditions, an element of join.getOnList() is null at index j. This is a server-side data-structure invariant violation, not a user-input validation error.
Source
Thrown at APIJSONORM/src/main/java/apijson/orm/AbstractSQLExecutor.java:611
columnIndexAndJoinMap[i - 1] = curJoin;
}
// 如果是主表则直接用主表对应的 item,否则缓存副表数据到 childMap
Join prevJoin = columnIndexAndJoinMap == null || i < 2 ? null : columnIndexAndJoinMap[i - 2];
if (curJoin != prevJoin) { // 前后字段不在同一个表对象,即便后面出现 null,也不该是主表数据,而是逻辑 bug 导致
SQLConfig<T, M, L> viceConfig = curJoin != null && curJoin.isSQLJoin() ? curJoin.getCacheConfig() : null;
boolean hasPK = false;
if (viceConfig != null) { //FIXME 只有和主表关联才能用 item,否则应该从 childMap 查其它副表数据
List<On> onList = curJoin.getOnList();
int size = onList == null ? 0 : onList.size();
if (size > 0) {
String idKey = viceConfig.getIdKey();
String tblKey = config.gainTableKey();
for (int j = size - 1; j >= 0; j--) {
On on = onList.get(j);
String ok = on == null ? null : on.getOriginKey();
if (ok == null) {
throw new NullPointerException("服务器内部错误,List<Join> 中 Join.onList[" + j + (on == null ? "] = null!" : ".getOriginKey() = null!"));
}
String k = ok.substring(0, ok.length() - 1);
String ttk = on.getTargetTableKey();
M target = StringUtil.equals(ttk, tblKey) ? item : (viceItem == null ? null : JSON.get(viceItem, ttk));
Object v = target == null ? null : target.get(on.getTargetKey());
hasPK = hasPK || (k.equals(idKey) && v != null);
viceConfig.putWhere(k, v, true);
}
}
}
if (viceConfig == null) { // StringUtil.isEmpty(viceSql, true)) {
Log.i(TAG, "execute viceConfig == null >> item = null; >> ");
curItem = null;
}
View on GitHub (pinned to 5284052872)
Solutions
- Fix the joiner syntax so every ON entry parses fully: "Table/alias/key@/Target/alias2/key".
- If constructing Join objects in code, never add null On entries; validate before adding.
- Align APIJSON artifact versions (ORM vs framework) across the classpath.
- Report with full request body if the joiner string itself looks correct — it may be an internal bug.
Example fix
// before join.setOnList(Arrays.asList(on, null)); // after join.setOnList(Collections.singletonList(on));
Defensive patterns
Strategy: try-catch
Try / catch
try { result = executor.execute(config); } catch (npe) { if (npe instanceof NullPointerException && /Join\.onList\[\d+\] = null/.test(npe.message)) { log.error('join onList corrupt for {}', config.getTable(), npe); return serverError(); } throw npe; } Prevention
- Do not hand-construct Join/On lists; use the joiner-string parser.
- Filter null On entries before setOnList in extension code.
- Keep all APIJSON modules at one version.
When it happens
Trigger: A JOIN (typically APP JOIN on cached data) whose onList contains a null entry — usually from programmatic construction of Join/On objects or a partial deserialization of a joiner string.
Common situations: Building Join objects manually in extended code; version mismatches between APIJSON modules producing incompletely populated Join instances; malformed "Table/key@/Target/key" joiner strings that parse into sparse lists.
Related errors
- 服务器内部错误,List<Join> 中 Join.onList[{}].getOriginKey() = null!
- 服务器内部错误,List<Join> 中 Join.onList[0] = null!
- 服务器内部错误,List<Join> 中 Join.onList[0].getOriginKey() = null!
- 服务器内部错误,List<Join> 中 Join.onList[0].getKey() = null!
- 服务器内部错误,解析子查询 {}/{}:{ } 为 Subquery 对象失败!
AI-assisted analysis of Tencent/APIJSON@5284052872 (2026-08-14).
Data as JSON: /api/errors/ef8dfa5d3060b00f.
Report an issue: GitHub.