{"record":{"id":"753379cb7b845f59","repo":"spring-projects/spring-ai","slug":"only-text-documents-are-supported-for-now-one-of","errorCode":null,"errorMessage":"Only text documents are supported for now. One of the documents contains non-text content.","messagePattern":"Only text documents are supported for now\\. One of the documents contains non-text content\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/observation/AbstractObservationVectorStore.java","lineNumber":93,"sourceCode":"\tpublic void add(List<Document> documents) {\n\t\tvalidateNonTextDocuments(documents);\n\t\tVectorStoreObservationContext observationContext = this\n\t\t\t.createObservationContextBuilder(VectorStoreObservationContext.Operation.ADD.value())\n\t\t\t.build();\n\n\t\tVectorStoreObservationDocumentation.AI_VECTOR_STORE\n\t\t\t.observation(this.customObservationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,\n\t\t\t\t\tthis.observationRegistry)\n\t\t\t.observe(() -> this.doAdd(documents));\n\t}\n\n\tprivate void validateNonTextDocuments(List<Document> documents) {\n\t\tif (documents == null) {\n\t\t\treturn;\n\t\t}\n\t\tfor (Document document : documents) {\n\t\t\tif (document != null && !document.isText()) {\n\t\t\t\tthrow new IllegalArgumentException(\n\t\t\t\t\t\t\"Only text documents are supported for now. One of the documents contains non-text content.\");\n\t\t\t}\n\t\t}\n\t}\n\n\t@Override\n\tpublic void delete(List<String> deleteDocIds) {\n\n\t\tVectorStoreObservationContext observationContext = this\n\t\t\t.createObservationContextBuilder(VectorStoreObservationContext.Operation.DELETE.value())\n\t\t\t.build();\n\n\t\tVectorStoreObservationDocumentation.AI_VECTOR_STORE\n\t\t\t.observation(this.customObservationConvention, DEFAULT_OBSERVATION_CONVENTION, () -> observationContext,\n\t\t\t\t\tthis.observationRegistry)\n\t\t\t.observe(() -> this.doDelete(deleteDocIds));\n\t}\n","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/spring-ai-vector-store/src/main/java/org/springframework/ai/vectorstore/observation/AbstractObservationVectorStore.java#L75-L111","documentation":"AbstractObservationVectorStore.add validates documents before embedding/upserting: multimodal (non-text) Documents are not supported by vector stores. validateNonTextDocuments throws IllegalArgumentException if any non-null document reports isText() == false, because current embedding and storage paths handle text content only.","triggerScenarios":"Calling vectorStore.add(List.of(doc)) or add(List.of(doc), options) with a Document built from media/other modality (Document.builder().media(...)) instead of text content.","commonSituations":"Multimodal RAG pipelines feeding image/audio Documents into a text-only vector store; upgrading to a Spring AI version where add() started validating document modality; generic ingestion code that mixes modalities.","solutions":["Only pass text-content Documents to vectorStore.add(); convert media to text (transcribe/OCR) first","Filter the list before calling add: documents.stream().filter(Document::isText).toList()","Route non-text documents to a multimodal-capable store or handle them in a separate pipeline","Check Document.isText() when building ingestion batches and log/skip offending documents"],"exampleFix":"// before\nvectorStore.add(documents);\n// after\nvectorStore.add(documents.stream().filter(Document::isText).toList());","handlingStrategy":"validation","validationCode":"List<Document> textDocs = documents == null ? List.of() : documents.stream().filter(d -> d != null && d.isText()).toList();","typeGuard":"boolean isAddable(Document d) { return d != null && d.isText(); }","tryCatchPattern":"try { vectorStore.add(docs); }\ncatch (IllegalArgumentException e) { if (e.getMessage().contains(\"non-text\")) { /* filter and retry */ } else throw e; }","preventionTips":["Filter by Document.isText() before add()","Separate multimodal documents into dedicated pipelines"],"tags":["vector-store","documents","multimodal","validation"],"backgroundTag":"unsupported-operation","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}