{"record":{"id":"facf8db0f92fa9d1","repo":"jd-opensource/joyagent-jdgenie","slug":"error-facf8d","errorCode":null,"errorMessage":"元数据集合为空！","messagePattern":"元数据集合为空！","errorType":"validation","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"genie-backend/src/main/java/com/jd/genie/service/QdrantService.java","lineNumber":143,"sourceCode":"    public void deletePointsSync(String collectionName, List<Points.PointId> ids) throws ExecutionException, InterruptedException {\n        client.deleteAsync(collectionName, ids).get();\n    }\n\n    public void deleteByFilterSync(String collectionName, Points.Filter filter) throws ExecutionException, InterruptedException {\n        client.deleteAsync(collectionName, filter).get();\n    }\n\n    public Points.UpdateResult upsertVectors(String collectionName, List<List<Float>> vectors, List<Map<String, JsonWithInt.Value>> payloads) throws ExecutionException, InterruptedException {\n        if (StringUtils.isBlank(collectionName)) {\n            throw new RuntimeException(\"集合名为空！\");\n        }\n\n        if (CollectionUtils.isEmpty(vectors)) {\n            throw new RuntimeException(\"向量集合为空！\");\n        }\n\n        if (CollectionUtils.isEmpty(payloads)) {\n            throw new RuntimeException(\"元数据集合为空！\");\n        }\n\n        if (vectors.size() != payloads.size()) {\n            throw new RuntimeException(\"向量集合大小与元数据集合大小不一致，vectorSize：\" + vectors.size() + \"，payloadSize：\" + payloads.size());\n        }\n\n        List<Points.PointStruct> pointStructList = new ArrayList<>();\n        for (int i = 0; i < vectors.size(); i++) {\n            Points.PointStruct pointStruct = Points.PointStruct.newBuilder()\n                    .setId(id(UUID.randomUUID()))\n                    .setVectors(vectors(vectors.get(i)))\n                    .putAllPayload(payloads.get(i))\n                    .build();\n            pointStructList.add(pointStruct);\n        }\n\n        return client.upsertAsync(collectionName, pointStructList).get();\n    }","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/genie-backend/src/main/java/com/jd/genie/service/QdrantService.java#L125-L161","documentation":"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.","triggerScenarios":"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.","commonSituations":"Upstream metadata builder skipped; developer passing only vectors assuming payloads optional; deserialization of metadata returning empty list.","solutions":["Populate payloads with one entry per vector (use an empty value map if no metadata)","If payloads are genuinely optional, use a different API path or pass placeholder payloads","Check the metadata assembly code for the bug leaving the list empty"],"exampleFix":"// before\nList<Map<String, JsonWithInt.Value>> payloads = new ArrayList<>(); // never filled\nqdrantService.upsertVectors(collection, vectors, payloads);\n// after\nList<Map<String, JsonWithInt.Value>> payloads = vectors.stream()\n    .map(v -> new HashMap<String, JsonWithInt.Value>())\n    .collect(Collectors.toList());\nqdrantService.upsertVectors(collection, vectors, payloads);","handlingStrategy":"validation","validationCode":"if (payloads == null || payloads.isEmpty()) {\n    throw new IllegalStateException(\"payloads required, one per vector\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    qdrantService.upsertVectors(collectionName, vectors, payloads);\n} catch (RuntimeException e) {\n    if (\"元数据集合为空！\".equals(e.getMessage())) {\n        log.error(\"payload list empty for upsert of {} vectors\", vectors.size());\n    } else throw e;\n}","preventionTips":["Build payloads in the same loop that builds vectors","Pass empty placeholder maps if a point genuinely has no metadata","Keep vectors and payloads together in a pair record until the call"],"tags":["java","qdrant","vector-database","validation"],"backgroundTag":"empty-required-field","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}