spring-projects/spring-ai · error · IllegalStateException

Delete operation failed

Error message

Delete operation failed

What it means

ElasticsearchVectorStore.doDelete(List<String>) issues a BulkRequest of delete operations; if the BulkResponse reports errors(), it throws IllegalStateException("Delete operation failed"). The individual item errors are not inspected, so any single failing delete (missing doc, version conflict, index closed) causes this blanket failure.

Source

Thrown at vector-stores/spring-ai-elasticsearch-store/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java:223

			}
		}
	}

	private Object getDocument(Document document, float[] embedding, String embeddingFieldName) {
		Assert.notNull(document.getText(), "document's text must not be null");

		return Map.of("id", document.getId(), "content", document.getText(), "metadata", document.getMetadata(),
				embeddingFieldName, embedding);
	}

	@Override
	public void doDelete(List<String> idList) {
		BulkRequest.Builder bulkRequestBuilder = new BulkRequest.Builder();
		for (String id : idList) {
			bulkRequestBuilder.operations(op -> op.delete(idx -> idx.index(this.options.getIndexName()).id(id)));
		}
		if (bulkRequest(bulkRequestBuilder.build()).errors()) {
			throw new IllegalStateException("Delete operation failed");
		}
	}

	@Override
	public void doDelete(Filter.Expression filterExpression) {
		try {
			this.elasticsearchClient.deleteByQuery(d -> d.index(this.options.getIndexName())
				.query(q -> q.queryString(qs -> qs.query(getElasticsearchQueryString(filterExpression)))));
		}
		catch (Exception e) {
			throw new IllegalStateException("Failed to delete documents by filter", e);
		}
	}

	private BulkResponse bulkRequest(BulkRequest bulkRequest) {
		try {
			return this.elasticsearchClient.bulk(bulkRequest);
		}

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Inspect Elasticsearch cluster logs / bulk response item failures for the concrete per-item error
  2. Verify options.getIndexName() matches an existing, writable index
  3. Check cluster disk watermarks and index read-only blocks (index.blocks.read_only_allow_delete)
  4. Retry with valid IDs; accept 404s for idempotent deletes by checking existence first

Example fix

// before: blind delete of possibly-removed docs
delete(List.of("doc-1", "doc-2"));
// after: filter to existing docs
List<String> existing = ids.stream().filter(id -> documentExists(id)).toList();
if (!existing.isEmpty()) delete(existing);
Defensive patterns

Strategy: validation

Validate before calling

List<String> existing = ids.stream()
    .filter(id -> elasticsearchClient.get(g -> g.index(indexName).id(id), Map.class).found())
    .toList();
if (!existing.isEmpty()) vectorStore.delete(existing);

Try / catch

try {
    vectorStore.delete(ids);
} catch (IllegalStateException e) {
    logger.warn("Some bulk deletes failed; inspect ES item errors", e);
}

Prevention

When it happens

Trigger: Calling vectorStore.delete(List<String> ids) where at least one bulk delete item fails in Elasticsearch (document not found with strict settings, version conflict, index missing/readonly).

Common situations: Deleting documents already removed by another process, index in read-only mode due to disk watermark, wrong index name configured in ElasticsearchVectorStoreOptions, or concurrent writes causing conflicts.

Related errors


AI-assisted analysis of spring-projects/spring-ai@98a7beda4f (2026-09-11). Data as JSON: /api/errors/84868543384d3652. Report an issue: GitHub.