jd-opensource/joyagent-jdgenie · error · RuntimeException

向量集合大小与元数据集合大小不一致,vectorSize:

Error message

向量集合大小与元数据集合大小不一致,vectorSize:{" + vectors.size() + "},payloadSize:{" + payloads.size() + "}

What it means

upsertVectorsPayloadTrans enforces vectors.size() == payloads.size() so each vector is stored with exactly one payload by index. This guard fires on a length mismatch; the message includes both sizes.

Solutions

  1. Build vectors, payloads, and ids in a single iteration over the same source items so sizes cannot diverge.
  2. Use the vectorSize/payloadSize values in the message to identify which side is short and inspect that pipeline stage.
  3. Add a caller-side assertion with per-item diagnostics before calling the service.
  4. If items can legitimately lack metadata, pad with empty maps instead of omitting entries.

Example fix

// before
items.forEach(i -> vectors.add(embed(i)));
items.stream().filter(i -> i.hasMeta()).forEach(i -> payloads.add(toPayload(i))); // diverges
service.upsertVectorsPayloadTrans(collection, ids, vectors, payloads);
// after
for (Item i : items) {
    vectors.add(embed(i));
    payloads.add(toPayload(i)); // always add, empty map if no meta
}
service.upsertVectorsPayloadTrans(collection, ids, vectors, payloads);
Defensive patterns

Strategy: validation

Validate before calling

if (vectors == null || payloads == null || vectors.size() != payloads.size()) {
    throw new IllegalArgumentException("size mismatch before upsertVectorsPayloadTrans: vectors="
        + (vectors == null ? "null" : vectors.size()) + " payloads=" + (payloads == null ? "null" : payloads.size()));
}

Type guard

static boolean areParallel(List<?> a, List<?> b) {
    return a != null && b != null && a.size() == b.size();
}

Try / catch

try {
    service.upsertVectorsPayloadTrans(collection, ids, vectors, payloads);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().contains("大小不一致")) {
        log.error("Trans upsert parallel-list mismatch: {}", e.getMessage());
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling upsertVectorsPayloadTrans where the vector list and payload list have different element counts, e.g. 50 embeddings but 49 payloads because one document's metadata extraction was skipped.

Common situations: Per-item metadata generation failing for some items while embedding succeeded for all; chunking/merging bugs when splitting large documents; concurrent population of the lists; filtering applied to one list after both were built.

Related errors


AI-assisted analysis of jd-opensource/joyagent-jdgenie@2417e0b8b6 (2026-09-08). Data as JSON: /api/errors/c3202d82bd1fb55f. Report an issue: GitHub.

Appendix: source

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

    public Points.UpdateResult upsertVectorsPayloadTrans(String collectionName, List<String> idList, List<List<Float>> vectors, List<Map<String, Object>> 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<Map<String, JsonWithInt.Value>> maps = transPayloadMap(payloads);

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

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

    public Points.UpdateResult upsertVector(String collectionName, List<Float> vector, Map<String, JsonWithInt.Value> payload) throws ExecutionException, InterruptedException {

View on GitHub (pinned to 2417e0b8b6)