-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Please do a quick search on GitHub issues first, there might be already a duplicate issue for the one you are about to create.
If the bug is trivial, just go ahead and create the issue. Otherwise, please take a few moments and fill in the following sections:
Bug description
QdrantVectorStore throws a NullPointerException when adding a Document
that contains media only (no text).
Environment
spring-ai-bom:1.0.0
spring-ai-starter-vector-store-qdrant
Java : 24
springboot version : 3.5.0
spring dependency management : version 1.1.7
Steps to reproduce
- Run Qdrant locally (
docker run -p 6333:6333 -p 6334:6334 qdrant/qdrant). - Create a Spring Boot app with
spring-ai-starter-vector-store-qdrant. - Inside a test or service method:
Media media = new Media(
MimeType.valueOf("image/png"),
new byte[] { 0x00 }); // 1×1 transparent pixel
Document imgDoc = Document.builder()
.media(media) // ⚠️ no text
.metadata(Map.of("fileName", "pixel.png"))
.build();
vectorStore.add(List.of(imgDoc)); // ← NPE here
Observe the stack trace:
Caused by: java.lang.RuntimeException: java.lang.NullPointerException
at org.springframework.ai.vectorstore.qdrant.QdrantVectorStore.toPayload(QdrantVectorStore.java:304)
at org.springframework.ai.vectorstore.qdrant.QdrantVectorStore.lambda$doAdd$0(QdrantVectorStore.java:186)
Expected behavior
QdrantVectorStore should accept media-only documents and store their vector plus metadata without requiring doc_content to be present.
Minimal Complete Reproducible example
When a Document instance contains only media (no text) and is passed to QdrantVectorStore.add(...), the call fails with a NullPointerException.
The failure originates in QdrantVectorStore.toPayload(Document):
var payload = QdrantValueFactory.toValueMap(document.getMetadata());
payload.put(CONTENT_FIELD_NAME,
io.qdrant.client.ValueFactory.value(document.getText())); // ← getText() is nullBecause Document was refactored to be either text or media (never both), getText() legitimately returns null for image-only documents.
The method still unconditionally adds the "doc_content" field, so a media document triggers the NPE during ValueFactory.value(null).
Typical flow that exposes the bug:
My custom EmbeddingModel converts each incoming image to a float-array vector via a FastAPI CLIP endpoint.
I build a list of media-only Document objects, one per uploaded file.
I inject VectorStore (backed by QdrantVectorStore) and call vectorStore.add(documents).
doAdd(...) calls toPayload(document) for every item; the very first image document crashes with the NPE, aborting the entire batch.
The problem is independent of the embedding model: it happens before the vectors are sent to Qdrant, purely because the payload builder assumes text content is always present.