jd-opensource/joyagent-jdgenie · error · RuntimeException
modelCode:
Error message
modelCode:
What it means
Nl2SqlService.queryData parses each generated NL2SQL SELECT statement to extract the FROM table (the model code) and looks it up in the model schema map built from schemaInfo. If the parsed table name has no matching ChatModelInfoDto, the service cannot resolve columns or the physical table, so it throws RuntimeException("modelCode:<code>不存在") meaning the model code does not exist.
Solutions
- Check the modelCode printed in the exception and verify it exists in the data-agent's model schema list (schemaInfo / ChatModelInfoDto)
- Regenerate the NL2SQL with a prompt that restricts tables to the registered model codes
- Fix or restore the model code in the data-agent configuration if it was renamed or deleted
- Check for case or whitespace mismatch between the SQL FROM table and the modelCode key
Example fix
// before
String modelCode = sqlModel.getFromTable().getTableName();
ChatModelInfoDto modelInfo = modelMap.get(modelCode);
// after
String modelCode = sqlModel.getFromTable().getTableName();
ChatModelInfoDto modelInfo = modelMap.getOrDefault(modelCode.toLowerCase(), modelMap.get(modelCode));
if (modelInfo == null) {
throw new RuntimeException("modelCode:" + modelCode + "不存在");
} Defensive patterns
Strategy: validation
Validate before calling
if (!modelMap.containsKey(sqlModel.getFromTable().getTableName())) {
throw new IllegalArgumentException("unknown modelCode: " + sqlModel.getFromTable().getTableName());
} Try / catch
try {
queryData(request);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().startsWith("modelCode:")) {
log.error("Unknown model in NL2SQL result: {}", e.getMessage());
// regenerate NL2SQL or return a friendly error to the caller
} else throw e;
} Prevention
- Always generate NL2SQL with the prompt restricted to registered model codes
- Validate the FROM table against the model map before executing further parsing
- Keep model codes normalized (consistent case) between schema registration and SQL generation
When it happens
Trigger: The NL2SQL generated by the LLM references a table/model code not present in the schema info returned for this data agent: the model was renamed or deleted, the SQL hallucinates a table name, or the parsed FROM table differs in case/alias from the registered modelCode.
Common situations: LLM hallucinating table names on ambiguous schemas; a model (collection) deleted or renamed in the data-agent config while the prompt context still mentions it; case-sensitive mismatch between the SQL table name and modelCode; stale NL2SQL results reused after schema changes.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- step_index is required for mark_step command
- nl2sql返回对象为空
- collectionName is empty
- vector is empty
- 集合名为空!
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/a012dc6ace00f478.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/service/Nl2SqlService.java:134
return modelInfo.getContent();
} else if ("sql".equalsIgnoreCase(modelInfo.getType())) {
return "(" + modelInfo.getContent() + ") t";
} else {
throw new RuntimeException("不支持的模型类型" + modelInfo.getType());
}
}
public List<ChatQueryData> queryData(NL2SQLReq request, NL2SQLResult nl2SQLResult) throws Exception {
List<NL2SQLResult.NL2SQLData> data = nl2SQLResult.getData();
List<ChatQueryData> dataList = new ArrayList<>();
List<ChatModelInfoDto> schemaInfo = request.getSchemaInfo();
Map<String, ChatModelInfoDto> modelMap = schemaInfo.stream().collect(Collectors.toMap(ChatModelInfoDto::getModelCode, v -> v));
for (NL2SQLResult.NL2SQLData nl2SQLData : data) {
SqlModel sqlModel = SqlParserUtils.parseSelectSql(nl2SQLData.getNl2sql(), dataAgentConfig.getDbConfig().getType());
String modelCode = sqlModel.getFromTable().getTableName();
ChatModelInfoDto modelInfo = modelMap.get(modelCode);
if (modelInfo == null) {
throw new RuntimeException("modelCode:" + modelCode + "不存在");
}
Map<String, ChatSchemaDto> columnMap = modelInfo.getSchemaList().stream().collect(Collectors.toMap(ChatSchemaDto::getColumnId, t -> t));
List<ChatQueryColumn> chatQueryColumns = parseColumns(sqlModel, columnMap);
List<ChatQueryFilter> chatQueryFilters = parseFilters(sqlModel, columnMap);
String tableName = getTableName(modelInfo);
String realSql = nl2SQLData.getNl2sql();
for (String key : modelMap.keySet()) {
realSql = realSql.replaceAll(key + "|`" + key + "`", tableName);
}
log.info("{},{} 执行sql:{}", request.getTraceId(), request.getRequestId(), realSql);
JdbcQueryRequest jdbcQueryRequest = new JdbcQueryRequest();
DbConfig dbConfig = dataAgentConfig.getDbConfig();
jdbcQueryRequest.setJdbcConnectionConfig(JdbcUtils.parseJdbcConnectionConfig(dbConfig));
jdbcQueryRequest.setSql(realSql);
QueryResult queryResult = jdbcDataProvider.queryData(jdbcQueryRequest);
log.info("{},{} 查询sql结果大小:{}", request.getTraceId(), request.getRequestId(), queryResult.getDataSize());
ChatQueryData queryData = new ChatQueryData();
queryData.setColumnList(chatQueryColumns);View on GitHub (pinned to 2417e0b8b6)