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

  1. Verify the embedding generation step upstream and check its logs for failures
  2. Assert the vector is non-empty (and of expected dimension) before calling search
  3. 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

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)