spring-projects/spring-ai · error · IllegalStateException

Failed to delete nodes by filter

Error message

Failed to delete nodes by filter

What it means

Neo4jVectorStore.doDelete wraps any exception thrown while executing the Cypher node-deletion (by id list or by filter expression) in an IllegalStateException with this message. It is a defensive wrapper so callers get a uniform runtime exception; the original cause is attached as the cause and also logged. The failure almost always originates in the Neo4j driver, Cypher syntax, or schema/constraint problems.

Source

Thrown at vector-stores/spring-ai-neo4j-store/src/main/java/org/springframework/ai/vectorstore/neo4j/Neo4jVectorStore.java:271

			String whereClause = this.filterExpressionConverter.convertExpression(filterExpression);

			// Create Cypher query with transaction batching
			String cypher = """
					MATCH (node:%s) WHERE %s
					CALL { WITH node DETACH DELETE node } IN TRANSACTIONS OF $transactionSize ROWS
					""".formatted(this.label, whereClause);

			var summary = session.run(cypher, Map.of("transactionSize", DEFAULT_TRANSACTION_SIZE)).consume();

			if (logger.isDebugEnabled()) {
				logger.debug("Deleted " + summary.counters().nodesDeleted() + " nodes matching filter expression");
			}
		}
		catch (Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error("Failed to delete nodes by filter: " + e.getMessage(), e);
			}
			throw new IllegalStateException("Failed to delete nodes by filter", e);
		}
	}

	@Override
	public List<Document> doSimilaritySearch(SearchRequest request) {
		Assert.isTrue(request.getTopK() > 0, "The number of documents to returned must be greater than zero");
		Assert.isTrue(request.getSimilarityThreshold() >= 0 && request.getSimilarityThreshold() <= 1,
				"The similarity score is bounded between 0 and 1; least to most similar respectively.");

		var embedding = Values.value(this.embeddingModel.embed(request.getQuery()));
		try (var session = this.driver.session(this.sessionConfig)) {
			StringBuilder condition = new StringBuilder("score >= $threshold");
			if (request.hasFilterExpression()) {
				Assert.state(request.getFilterExpression() != null, "filter expression can't be null");
				condition.append(" AND ")
					.append(this.filterExpressionConverter.convertExpression(request.getFilterExpression()));
			}
			String query = """

View on GitHub (pinned to 98a7beda4f)

Solutions

  1. Inspect the chained cause (e.getCause()) and the logged 'Failed to delete nodes by filter' stack trace for the underlying driver/Cypher error.
  2. Verify Neo4j connectivity and credentials in the store configuration (uri, username, password).
  3. Validate the filter expression syntax; test it against Filter.ExpressionBuilder or run the resulting Cypher manually in the Neo4j browser.
  4. Confirm the configured label/embedding property names match the actual Neo4j schema.

Example fix

// before
delete("country == 'IN' AND age IN [18,25]"); // typo in filter leads to bad Cypher
// after
delete(new Filter.Expression(AND, new Eq("country", "IN"), new In("age", List.of(18, 25))));
Defensive patterns

Strategy: try-catch

Validate before calling

// before delete
try (Driver driver = GraphDatabase.driver(uri, AuthTokens.basic(user, pass))) {
    driver.verifyConnectivity(); // fail fast if Neo4j is unreachable
}

Try / catch

try {
    vectorStore.delete(idList);
} catch (IllegalStateException e) {
    logger.error("Neo4j delete failed: {}", e.getCause() != null ? e.getCause().getMessage() : e.getMessage(), e);
}

Prevention

When it happens

Trigger: Calling VectorStore.delete(List<String> idList) or delete(Filter.Expression) / delete(String filterExpression) on a Neo4jVectorStore when the Neo4j database is unreachable, the Cypher generated from the filter expression fails, or the session/transaction errors.

Common situations: Neo4j browser not running or wrong bolt URL in config; invalid filter expression string producing bad Cypher; deleted/renamed node labels or properties; Neo4j authentication failure; transient network drop during delete.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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