jd-opensource/joyagent-jdgenie · error · RuntimeException
tableRag result is null
Error message
tableRag result is null
What it means
TableRagService.tableRag throws this when the HTTP response from the data-agent TABLE_RAG_URL endpoint cannot be parsed into a TableRagResult or parses to an object with a null code. It indicates the remote table-RAG service returned an empty, malformed, or non-standard body, so no valid response envelope exists.
Solutions
- Verify dataAgentConfig.getAgentUrl() + TABLE_RAG_URL is reachable (curl the endpoint with an equivalent payload).
- Log the raw response string res before parsing to see what the remote service actually returned.
- Check data-agent service health/logs for the corresponding traceId/requestId.
- Wrap the POST with retry/timeout handling so transient network failures surface as a clear upstream error instead of a null parse.
Example fix
// before
TableRagResult tableRagResult = JSONObject.parseObject(res, TableRagResult.class);
if (tableRagResult == null || tableRagResult.getCode() == null) {
throw new RuntimeException("tableRag result is null");
}
// after
if (StringUtils.isBlank(res)) {
throw new RuntimeException("tableRag returned empty body, url=" + dataAgentConfig.getAgentUrl() + TABLE_RAG_URL);
}
TableRagResult tableRagResult = JSONObject.parseObject(res, TableRagResult.class);
if (tableRagResult == null || tableRagResult.getCode() == null) {
throw new RuntimeException("tableRag result unparseable, body=" + res);
} Defensive patterns
Strategy: validation
Validate before calling
// java
if (StringUtils.isBlank(res)) {
throw new IllegalStateException("tableRag upstream returned empty body");
} Type guard
TableRagResult safeParse(String res) {
if (StringUtils.isBlank(res)) return null;
try {
return JSONObject.parseObject(res, TableRagResult.class);
} catch (Exception e) {
return null;
}
} Try / catch
try {
TableRagResult r = tableRagService.tableRag(req);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("tableRag result is null")) {
log.error("tableRag upstream unavailable, check dataAgent url/health");
}
throw e;
} Prevention
- Log the raw upstream response before parsing so bad bodies are visible.
- Monitor data-agent endpoint health and configure timeouts on the HTTP client.
- Pin/verify TableRagResult fields against the data-agent's actual response contract.
When it happens
Trigger: OkHttpUtil.postJsonBody returns null or an empty/garbage string (network failure path, agent URL wrong, gateway returning HTML/empty body), making JSONObject.parseObject(res, TableRagResult.class) yield null or an object without code.
Common situations: Data-agent service down or returning 5xx with empty body; dataAgentConfig.getAgentUrl() misconfigured or pointing to a wrong port; proxy/gateway intercepting the request and returning an error page; serialization/deserialization mismatch after TableRagResult model changes.
Related errors
- tableRag server return error
- 调用接口" + url + "失败:" + response.message()
- 向量生成失败!
- 返回结果为空!
- Tool execution failed: " + error
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/f37389f71573d596.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/service/TableRagService.java:45
@Autowired
DataAgentConfig dataAgentConfig;
public List<ChatSchemaDto> tableRag(NL2SQLReq req) throws IOException {
if (!dataAgentConfig.getEsConfig().getEnable() && !dataAgentConfig.getQdrantConfig().getEnable()) {
log.info("{},{} 未开启向量和es,不进行tableRag",req.getTraceId(),req.getRequestId());
return new ArrayList<>();
}
String res;
try {
res = OkHttpUtil.postJsonBody(dataAgentConfig.getAgentUrl() + TABLE_RAG_URL, null, JSONObject.toJSONString(req));
} catch (Exception e) {
log.warn("{},{} tableRag server error,retry:{}",req.getTraceId(),req.getRequestId(), e.getMessage());
res = OkHttpUtil.postJsonBody(dataAgentConfig.getAgentUrl() + TABLE_RAG_URL, null, JSONObject.toJSONString(req));
}
log.info("{},{} tableRag result:{}", req.getTraceId(),req.getRequestId(),res);
TableRagResult tableRagResult = JSONObject.parseObject(res, TableRagResult.class);
if (tableRagResult == null || tableRagResult.getCode() == null) {
throw new RuntimeException("tableRag result is null");
}
if (tableRagResult.getCode() != 200) {
throw new RuntimeException("tableRag server return error");
}
List<TableRagResult.TableRagData> data = tableRagResult.getData();
if (CollectionUtils.isEmpty(data)) {
throw new RuntimeException("tableRag result data is empty");
}
return data.stream()
.filter(Objects::nonNull)
.map(TableRagResult.TableRagData::getSchemaList)
.filter(CollectionUtils::isNotEmpty)
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
}
View on GitHub (pinned to 2417e0b8b6)