jd-opensource/joyagent-jdgenie · error · IllegalArgumentException
nl2sql返回对象为空
Error message
nl2sql返回对象为空
What it means
replaceFirstMatchedOrThrow decorates model code identifiers in the nl2sql-generated SQL with backticks. It throws IllegalArgumentException('nl2sql返回对象为空') when the input SQL or the code list is null/empty — i.e. the nl2sql result object lacked the data needed to post-process.
Solutions
- Ensure request.modelCodeList is populated with the model codes before calling NL2SQL
- Check the agent response item has a non-null nl2sql field
- If null input is legitimate, relax the guard to return input unchanged instead of throwing
Example fix
// before
if (input == null || codeList == null || codeList.isEmpty()) {
throw new IllegalArgumentException("nl2sql返回对象为空");
}
// after
if (input == null) {
return null;
}
if (codeList == null || codeList.isEmpty()) {
return input;
} Defensive patterns
Strategy: validation
Validate before calling
if (request.getModelCodeList() == null || request.getModelCodeList().isEmpty()) {
throw new IllegalArgumentException("modelCodeList is required");
}
// and ensure nl2SQLData.getNl2sql() != null before prettySql Type guard
boolean isDecoratable(String sql, List<String> codes) {
return sql != null && codes != null && !codes.isEmpty();
} Try / catch
try {
pretty = prettySql(data, request);
} catch (IllegalArgumentException e) {
log.warn("cannot decorate sql: {}", e.getMessage());
pretty = data.getNl2sql(); // fall back to raw sql
} Prevention
- Always populate modelCodeList in NL2SQLReq
- Null-check agent nl2sql output before post-processing
- Add unit tests for empty codeList paths
When it happens
Trigger: prettySql() calls replaceFirstMatchedOrThrow with nl2SQLData.getNl2sql()==null or request.getModelCodeList() empty/null.
Common situations: Agent returned a data item with no nl2sql field; frontend request omitted modelCodeList; older agent versions returning a different field name.
Related errors
- nl2sql result is null
- modelCode:
- Invalid tool_choice: " + toolChoice
- step_index is required for mark_step command
- 不支持的数据源类型:
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/45635e238b8db8bd.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/service/Nl2SqlService.java:78
Nl2SqlSseListener sqlSseListener = new Nl2SqlSseListener(emitter, request.getRequestId(), request.getTraceId());
OkHttpUtil.requestSse(dataAgentConfig.getAgentUrl() + NL2SQL_URL, null, JSONObject.toJSONString(request), sqlSseListener);
sqlSseListener.getCountDownLatch().await();
int eventCount = sqlSseListener.getEventCount();
log.info("{} sse event count:{}", request.getRequestId(), eventCount);
if (!sqlSseListener.isSuccess()) {
throw new RuntimeException("sse listener failed " + sqlSseListener.getErrorMessage());
}
NL2SQLResult nl2SQLResult = sqlSseListener.getNl2SQLResult();
if (err.get() != null) {
throw new RuntimeException("sse nl2sql failed:" + err.get().getMessage());
}
return nl2sqlQueryData(request, nl2SQLResult);
}
public String replaceFirstMatchedOrThrow(String input, List<String> codeList) {
if (input == null || codeList == null || codeList.isEmpty()) {
throw new IllegalArgumentException("nl2sql返回对象为空");
}
List<Pattern> patterns = codeList.stream()
.distinct()
.map(code -> Pattern.compile("(?i)(?<!`)\\b" + Pattern.quote(code) + "\\b(?!`)"))
.toList();
Matcher matcher;
for (Pattern pattern : patterns) {
matcher = pattern.matcher(input);
if (matcher.find()) {
return matcher.replaceFirst("`$0`");
}
}
return input;
}
private List<ChatQueryData> nl2sqlQueryData(NL2SQLReq request, NL2SQLResult nl2SQLResult) throws Exception {View on GitHub (pinned to 2417e0b8b6)