jd-opensource/joyagent-jdgenie · error · IllegalArgumentException
vector is empty
Error message
vector is empty
What it means
QdrantService.search requires a non-empty query vector to build the SearchPoints request. When the vector list is null or empty it throws IllegalArgumentException("vector is empty") instead of sending a malformed gRPC request.
Solutions
- Verify the embedding generation step upstream and check its logs for failures
- Assert the vector is non-empty (and of expected dimension) before calling search
- Fix embedding client configuration (API key, model name, dimension) if it silently returns empty
Example fix
// before
List<Float> vector = embed(queryText);
qdrantService.search(collection, vector, 10, null, null, 5L, TimeUnit.SECONDS, null);
// after
List<Float> vector = embed(queryText);
if (vector == null || vector.isEmpty()) {
throw new IllegalStateException("embedding failed for query: " + queryText);
}
qdrantService.search(collection, vector, 10, null, null, 5L, TimeUnit.SECONDS, null); Defensive patterns
Strategy: validation
Validate before calling
if (vector == null || vector.isEmpty() || vector.size() != EXPECTED_DIM) {
throw new IllegalArgumentException("query vector missing or wrong dimension");
} Type guard
boolean isValidVector(List<Float> v) {
return v != null && !v.isEmpty() && v.stream().allMatch(Objects::nonNull);
} Try / catch
try {
return qdrantService.search(collectionName, vector, limit, filter, null, timeout, TimeUnit.SECONDS, threshold);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("vector is empty")) {
log.error("embedding step produced empty vector");
}
return Collections.emptyList();
} Prevention
- Check the embedding result for null/empty immediately after the embedding call
- Validate vector dimension matches the collection's configured dimension
- Fail fast when the embedding API errors instead of propagating an empty list
When it happens
Trigger: Calling search with an empty/null vector: the embedding model returned nothing, the embedding call failed silently upstream, or a List<Float> was initialized but never populated.
Common situations: Embedding API returning empty response; wrong dimension handling dropping all values; passing an unpopulated list due to an error swallowed earlier in the pipeline.
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
AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08).
Data as JSON: /api/errors/1d70c4e7d231f669.
Report an issue: GitHub.
Appendix: source
Thrown at genie-backend/src/main/java/com/jd/genie/service/QdrantService.java:87
} else {
client = new QdrantClient(QdrantGrpcClient.newBuilder(dataAgentConfig.getQdrantConfig().getHost(), dataAgentConfig.getQdrantConfig().getPort(), false).build());
}
}
}
@Override
public void destroy() {
if (client != null) {
client.close();
}
}
public List<Points.ScoredPoint> search(String collectionName, List<Float> vector, int limit, Points.Filter filter, List<String> payloads, Long timeout, TimeUnit timeUnit, Float scoreThreshold) throws ExecutionException, InterruptedException, TimeoutException {
if (StringUtils.isBlank(collectionName)) {
throw new IllegalArgumentException("collectionName is empty");
}
if (CollectionUtils.isEmpty(vector)) {
throw new IllegalArgumentException("vector is empty");
}
Points.SearchPoints.Builder requestBuilder = Points.SearchPoints.newBuilder();
requestBuilder.setCollectionName(collectionName);
requestBuilder.addAllVector(vector);
requestBuilder.setLimit(Math.min(limit, maxLimitSize));
if (Objects.nonNull(payloads)) {
requestBuilder.setWithPayload(include(payloads));
} else {
requestBuilder.setWithPayload(enable(true));
}
if (Objects.nonNull(filter)) {
requestBuilder.setFilter(filter);
}
if (Objects.nonNull(scoreThreshold)) {
requestBuilder.setScoreThreshold(scoreThreshold);
}
View on GitHub (pinned to 2417e0b8b6)