jd-opensource/joyagent-jdgenie · error · RuntimeException
dataList is null!
Error message
dataList is null!
What it means
Validation in VectorService.saveVector: the dataList field of the VectorSaveReq (the vectors/metadata to persist) is null, so there is nothing to save. The method wraps its work in a broad try-catch that logs and rethrows as RuntimeException, so this input check is the fast-fail path before any Qdrant interaction; fires when callers submit a save request with an absent or empty data list.
Solutions
- Check dataList.size() > 0 at the caller before invoking saveVector and skip the call for empty batches.
- Investigate why the upstream pipeline produced zero records (source query, filters).
- If empty batches are legitimate, treat them as a no-op in the caller instead of an error.
- Ensure each VectorData in dataList has a non-blank embeddingText, since blank texts will produce useless embeddings.
Example fix
// before
vectorService.saveVector(buildSaveReq(records)); // records may be empty
// after
List<VectorSaveReq.VectorData> items = toVectorData(records);
if (items.isEmpty()) {
log.info("no records to save, skipping saveVector");
return true;
}
vectorService.saveVector(buildSaveReq(items)); Defensive patterns
Strategy: validation
Validate before calling
// java (caller)
if (saveReq.getDataList() == null || saveReq.getDataList().isEmpty()) {
return true; // nothing to save
} Type guard
boolean canSave(VectorSaveReq req) {
return req != null && CollectionUtils.isNotEmpty(req.getDataList());
} Try / catch
try {
vectorService.saveVector(saveReq);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("dataList is null")) {
log.warn("saveVector called with empty dataList — check upstream pipeline");
return false;
}
throw e;
} Prevention
- Treat empty batches as no-ops at the caller instead of calling saveVector.
- Alert when sync pipelines produce zero records — that usually precedes this error.
- Ensure each VectorData.embeddingText is non-blank before batching.
When it happens
Trigger: Calling saveVector with dataList == null or an empty list — typically an upstream batch/transform step produced zero records (e.g., source query returned nothing) and the result was passed through unchanged.
Common situations: Upstream data extraction returned no rows for the sync window; a filter step removed all items before save; caller misuses the API assuming saveVector handles empty batches as a no-op.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- 查询query为空!
- collectionName is null!
- step_index is required for mark_step command
- modelCode:
- collectionName is empty
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/c45a2b4435ce1870.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/service/VectorService.java:131
Map<String, JsonWithInt.Value> payloadMap = p.getPayloadMap();
payloadMap.forEach((k, v) -> hashMap.put(k, v.getStringValue()));
hashMap.put("score", p.getScore());
hashMap.put("_id", p.getId().getUuid());
return hashMap;
}).collect(Collectors.toList());
} catch (Exception e) {
log.error("vectorRecall error: req:{}", JSONObject.toJSONString(req), e);
throw new RuntimeException(e);
}
}
public Boolean saveVector(VectorSaveReq vectorSaveReq) {
try {
if (StringUtils.isBlank(vectorSaveReq.getCollectionName())) {
throw new RuntimeException("collectionName is null!");
}
if (CollectionUtils.isEmpty(vectorSaveReq.getDataList())) {
throw new RuntimeException("dataList is null!");
}
List<String> textList = vectorSaveReq.getDataList().stream().map(VectorSaveReq.VectorData::getEmbeddingText).collect(Collectors.toList());
List<List<Float>> vector = embeddingService.getVectorBatch(textList);
List<String> idList = vectorSaveReq.getDataList().stream().map(data -> {
if (StringUtils.isNotBlank(data.getUuid()) && isUuid(data.getUuid())) {
return data.getUuid();
}
return UUID.randomUUID().toString();
}).collect(Collectors.toList());
List<Map<String, Object>> payloads = vectorSaveReq.getDataList().stream().map(VectorSaveReq.VectorData::getPayloads).collect(Collectors.toList());
qdrantService.upsertVectorsPayloadTrans(vectorSaveReq.getCollectionName(), idList, vector, payloads);
return true;
} catch (Exception e) {
log.error("saveVector error: req:{}", JSONObject.toJSONString(vectorSaveReq), e);
return false;
}
}View on GitHub (pinned to 2417e0b8b6)