jd-opensource/joyagent-jdgenie · error · RuntimeException

元数据集合为空!

Error message

元数据集合为空!

What it means

Parameter validation in QdrantService.upsertVectors: the payload list (one metadata map per vector) is null or empty, so the batch upsert would be malformed — Qdrant points would lack their metadata. Like the sibling guards for collection name and vectors, it throws immediately before the client.upsertAsync RPC; fires when callers build an upsert request without supplying per-point metadata.

Solutions

  1. Populate payloads with one entry per vector (use an empty value map if no metadata)
  2. If payloads are genuinely optional, use a different API path or pass placeholder payloads
  3. Check the metadata assembly code for the bug leaving the list empty

Example fix

// before
List<Map<String, JsonWithInt.Value>> payloads = new ArrayList<>(); // never filled
qdrantService.upsertVectors(collection, vectors, payloads);
// after
List<Map<String, JsonWithInt.Value>> payloads = vectors.stream()
    .map(v -> new HashMap<String, JsonWithInt.Value>())
    .collect(Collectors.toList());
qdrantService.upsertVectors(collection, vectors, payloads);
Defensive patterns

Strategy: validation

Validate before calling

if (payloads == null || payloads.isEmpty()) {
    throw new IllegalStateException("payloads required, one per vector");
}

Try / catch

try {
    qdrantService.upsertVectors(collectionName, vectors, payloads);
} catch (RuntimeException e) {
    if ("元数据集合为空!".equals(e.getMessage())) {
        log.error("payload list empty for upsert of {} vectors", vectors.size());
    } else throw e;
}

Prevention

When it happens

Trigger: Calling upsertVectors(collection, vectors, payloads) with null/empty payloads while vectors is non-empty — e.g. metadata extraction returned nothing or the payload list was never built.

Common situations: Upstream metadata builder skipped; developer passing only vectors assuming payloads optional; deserialization of metadata returning empty list.

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

Appendix: source

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

    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);
        }

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

View on GitHub (pinned to 2417e0b8b6)