jd-opensource/joyagent-jdgenie · error · RuntimeException
向量生成失败!
Error message
向量生成失败!
What it means
VectorService.recall throws this when embeddingService.getVector(query) returns a null or empty vector, meaning the embedding model/service failed to produce an embedding for the query text. The recall cannot proceed without a vector to search with.
Solutions
- Check embedding service health and its logs for the failing request (URL, auth, payload).
- Validate embeddingService config (endpoint URL, API key, model name) is correct for the environment.
- Inspect getVector: it likely swallows errors and returns empty — make it throw with the upstream status/body so the root cause is visible.
- Add retry with backoff for transient embedding-service failures before giving up.
- Truncate/validate query length against the embedding model's token limit.
Example fix
// before
List<Float> vector = embeddingService.getVector(req.getQuery());
if (CollectionUtils.isEmpty(vector)) {
throw new RuntimeException("向量生成失败!");
}
// after
List<Float> vector = embeddingService.getVector(req.getQuery());
if (CollectionUtils.isEmpty(vector)) {
log.error("embedding failed, queryLen={}, req={}", req.getQuery().length(), JSONObject.toJSONString(req));
throw new RuntimeException("向量生成失败! query=" + req.getQuery());
} Defensive patterns
Strategy: retry
Validate before calling
// java (caller): sanity-check embedding availability indirectly
// ensure query is non-blank and within token limits before calling
if (StringUtils.isBlank(query) || query.length() > MAX_QUERY_LEN) {
throw new IllegalArgumentException("query empty or too long for embedding model");
} Try / catch
try {
return vectorService.vectorRecall(req);
} catch (RuntimeException e) {
if (e.getMessage() != null && e.getMessage().contains("向量生成失败")) {
// embedding service degraded: retry once, then fall back to keyword search
return fallbackKeywordSearch(req.getQuery());
}
throw e;
} Prevention
- Health-check the embedding service and alert on empty-vector rates.
- Validate embedding endpoint, API key, and model name per environment.
- Truncate queries to the model's token limit before embedding.
- Make getVector surface upstream HTTP errors rather than returning empty.
When it happens
Trigger: getVector returns empty because the embedding HTTP call failed or returned an unexpected body; query text is in a language/format the model rejects; embedding service credentials/URL misconfigured so the empty-vector branch is hit.
Common situations: Embedding service down or returning 4xx/5xx consumed as empty result; embedding API key expired; query exceeds model token limit and service silently returns nothing; model name changed after an upgrade.
Related errors
- tableRag result is null
- tableRag server return error
- 集合名称为空!
- 查询query为空!
- Tool execution failed: " + error
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/2df0239548c28d47.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/service/VectorService.java:80
log.error("vectorRecall error: req:{}", JSONObject.toJSONString(req), e);
if (future != null) {
try {
future.cancel(true);
} catch (Exception e1) {
log.error(e1.getMessage(), e1);
}
}
}
return new ArrayList<>();
}
private List<Map<String, Object>> recall(VectorRecallReq req) {
try {
List<Float> vector = embeddingService.getVector(req.getQuery());
if (CollectionUtils.isEmpty(vector)) {
log.error("vectorRecall error: vector is empty, req:{}", JSONObject.toJSONString(req));
throw new RuntimeException("向量生成失败!");
}
Points.Filter filter = null;
if (Objects.nonNull(req.getKeywordFilterMap()) && !req.getKeywordFilterMap().isEmpty()) {
Points.Filter.Builder filterBuilder = Points.Filter.newBuilder();
req.getKeywordFilterMap().forEach((k, v) -> {
if (v instanceof String) {
filterBuilder.addMust(matchKeyword(k, (String) v));
} else if (v instanceof Long) {
filterBuilder.addMust(match(k, (long) v));
} else if (v instanceof Integer) {
filterBuilder.addMust(match(k, (int) v));
} else if (v instanceof Boolean) {
filterBuilder.addMust(match(k, (boolean) v));
} else if (v instanceof List) {
List<Object> list = (List<Object>) v;
if (CollectionUtils.isNotEmpty(list)) {
Object type = list.get(0);View on GitHub (pinned to 2417e0b8b6)