jd-opensource/joyagent-jdgenie · error · RuntimeException

向量id集合为空!

Error message

向量id集合为空!

What it means

The id-bearing upsertVectors overload requires an explicit point ID per vector; a null/empty idList leaves points without deterministic IDs, so it throws RuntimeException("向量id集合为空!") (vector id collection is empty).

Solutions

  1. Populate idList with one ID per vector (UUID or business key)
  2. If you do not need explicit IDs, switch to the 3-arg upsertVectors(collectionName, vectors, payloads) which auto-generates UUIDs
  3. Check why the ID source list is empty upstream

Example fix

// before
qdrantService.upsertVectors(collection, new ArrayList<>(), vectors, payloads);
// after
List<String> idList = vectors.stream().map(v -> UUID.randomUUID().toString()).collect(toList());
qdrantService.upsertVectors(collection, idList, vectors, payloads);
Defensive patterns

Strategy: validation

Validate before calling

if (idList == null || idList.isEmpty() || idList.size() != vectors.size()) {
    throw new IllegalStateException("idList must contain one id per vector");
}

Try / catch

try {
    qdrantService.upsertVectors(collectionName, idList, vectors, payloads);
} catch (RuntimeException e) {
    if ("向量id集合为空!".equals(e.getMessage())) {
        log.error("no point ids supplied for id-based upsert");
    } else throw e;
}

Prevention

When it happens

Trigger: Calling upsertVectors(collectionName, idList, vectors, payloads) with an empty/null idList while vectors are present — the ID source query returned nothing or IDs were never collected.

Common situations: Upstream ID lookup returned empty; developer assumed IDs optional and used this overload instead of the id-less one; batch assembly forgot to add IDs.

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/39692419a25286cd. Report an issue: GitHub.

Appendix: source

Thrown at genie-backend/src/main/java/com/jd/genie/service/QdrantService.java:169

        for (int i = 0; i < vectors.size(); i++) {
            Points.PointStruct pointStruct = Points.PointStruct.newBuilder()
                    .setId(id(UUID.randomUUID()))
                    .setVectors(vectors(vectors.get(i)))
                    .putAllPayload(payloads.get(i))
                    .build();
            pointStructList.add(pointStruct);
        }

        return client.upsertAsync(collectionName, pointStructList).get();
    }

    public Points.UpdateResult upsertVectors(String collectionName, List<String> idList, List<List<Float>> vectors, List<Map<String, JsonWithInt.Value>> payloads) throws ExecutionException, InterruptedException {
        if (StringUtils.isBlank(collectionName)) {
            throw new RuntimeException("集合名为空!");
        }

        if (CollectionUtils.isEmpty(idList)) {
            throw new RuntimeException("向量id集合为空!");
        }

        if (CollectionUtils.isEmpty(vectors)) {
            throw new RuntimeException("向量集合为空!");
        }

        if (CollectionUtils.isEmpty(payloads)) {
            throw new RuntimeException("元数据集合为空!");
        }

        if (vectors.size() != payloads.size()) {
            throw new RuntimeException("向量集合大小与元数据集合大小不一致,vectorSize:" + vectors.size() + ",payloadSize:" + payloads.size());
        }

        List<Points.PointStruct> pointStructList = new ArrayList<>();
        for (int i = 0; i < vectors.size(); i++) {
            Points.PointStruct pointStruct = Points.PointStruct.newBuilder()
                    .setId(id(UUID.fromString(idList.get(i))))

View on GitHub (pinned to 2417e0b8b6)