jd-opensource/joyagent-jdgenie · error · RuntimeException

向量集合为空!

Error message

向量集合为空!

What it means

Parameter validation in QdrantService.upsertVectors: a batch upsert was requested against the Qdrant vector database but the collectionName argument is blank, so there is no target collection to write to. It is one of a series of per-argument guards (collection name, vectors, payloads) that fail fast with a Chinese-language RuntimeException before any RPC is attempted; fires when callers pass an unset or empty collection identifier.

Solutions

  1. Check upstream data pipeline for why zero vectors were produced
  2. Skip the call gracefully when the batch is empty instead of treating it as an error
  3. Log batch sizes at each pipeline stage to find where items were dropped

Example fix

// before
qdrantService.upsertVectors(collection, vectors, payloads);
// after
if (!vectors.isEmpty()) {
    qdrantService.upsertVectors(collection, vectors, payloads);
} else {
    log.warn("skip upsert: no vectors to write");
}
Defensive patterns

Strategy: validation

Validate before calling

if (vectors == null || vectors.isEmpty()) {
    return; // nothing to upsert, skip instead of erroring
}

Try / catch

try {
    qdrantService.upsertVectors(collectionName, vectors, payloads);
} catch (RuntimeException e) {
    if ("向量集合为空!".equals(e.getMessage())) {
        log.warn("empty vector batch skipped");
    } else throw e;
}

Prevention

When it happens

Trigger: Calling upsertVectors with an empty vectors list: the batch producer produced no records, an upstream embedding step returned nothing, or data was filtered out before the call.

Common situations: Empty input dataset or empty batch after filtering; embedding failures silently dropping all items; loop bug leaving the list unpopulated.

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/0a24b13fca1480a6. Report an issue: GitHub.

Appendix: source

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

                        .setWithPayload(enable(true))
                        .build()).get();
    }

    public void deletePointsSync(String collectionName, List<Points.PointId> ids) throws ExecutionException, InterruptedException {
        client.deleteAsync(collectionName, ids).get();
    }

    public void deleteByFilterSync(String collectionName, Points.Filter filter) throws ExecutionException, InterruptedException {
        client.deleteAsync(collectionName, filter).get();
    }

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

        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.randomUUID()))
                    .setVectors(vectors(vectors.get(i)))
                    .putAllPayload(payloads.get(i))
                    .build();
            pointStructList.add(pointStruct);

View on GitHub (pinned to 2417e0b8b6)