-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Description
Bug description
When mapping similarity search results to Document, the code injects a distance field into a JsonObject read from the row’s metadata. If rowRecord.get(metadataFieldName) returns null, the subsequent call to metadata.addProperty(...) throws an NPE. The code currently catches only ParamException, so a NullPointerException escapes the try/catch.
Stack trace (excerpt):
java.lang.NullPointerException: Cannot invoke "com.google.gson.JsonObject.addProperty(String, java.lang.Number)" because "metadata" is null
at org.springframework.ai.vectorstore.milvus.MilvusVectorStore.lambda$similaritySearch$2(...)
at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:...)
at org.springframework.ai.vectorstore...ObservationAwareMilvusVectorStore.lambda$similaritySearch$7(...)
at ai.shb.shbai.service.DocumentService.searchSimilarDocuments(DocumentService.java:397)
at ai.shb.shbai.controller.DocumentController.searchDocuments(DocumentController.java:36)
Environment
Spring AI version: 1.0.0
Java version: 17.0.14
Vector store: MilvusVectorStore
Gson version: 2.13.1
Module / file / class: org.springframework.ai.vectorstore.milvus.MilvusVectorStore
Steps to reproduce
-
Ensure a search result row where the metadata field exists but its value is null (common with legacy/custom data).
-
Run similarity search and map rows to Document with code like:
JsonObject metadata = (JsonObject) rowRecord.get(this.metadataFieldName); // may be null
metadata.addProperty(DocumentMetadata.DISTANCE.value(), 1 - getResultSimilarity(rowRecord)); // NPE here
Expected behavior
Missing/null metadata should be handled gracefully (use an empty metadata object/map as fallback).
distance is always injected.
Minimal Complete Reproducible example
Self-contained snippet that reproduces the failure without external deps:
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.Map;
public class MinimalRepo {
static Map<String, Object> mapRecord(Object rawMetadata, double similarity) {
JsonObject metadata = (JsonObject) rawMetadata; // may be null
// This line throws when metadata == null
metadata.addProperty("distance", 1.0 - similarity);
Type t = new TypeToken<Map<String, Object>>(){}.getType();
return new Gson().fromJson(metadata, t);
}
public static void main(String[] args) {
System.out.println("Testing with null metadata...");
try {
mapRecord(null, 0.8); // -> NullPointerException
} catch (NullPointerException e) {
System.out.println("✓ NullPointerException caught: " + e.getMessage());
e.printStackTrace();
}
}
}